1441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Pedantic checking of ELF files compliance with gABI/psABI spec. 2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. 3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This file is part of Red Hat elfutils. 4441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Written by Ulrich Drepper <drepper@redhat.com>, 2001. 5441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng it under the terms of the GNU General Public License as published by the 8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Free Software Foundation; version 2 of the License. 9441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng General Public License for more details. 14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng You should have received a copy of the GNU General Public License along 16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is an included package of the Open Invention Network. 20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng An included package of the Open Invention Network is a package for which 21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Open Invention Network licensees cross-license their patents. No patent 22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng license is granted, either expressly or impliedly, by designation as an 23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng included package. Should you wish to participate in the Open Invention 24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Network licensing program, please visit www.openinventionnetwork.com 25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng <http://www.openinventionnetwork.com>. */ 26441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 27441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#ifdef HAVE_CONFIG_H 28441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project# include <config.h> 29441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif 30441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 31441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <argp.h> 32441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <assert.h> 33441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <byteswap.h> 34441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <endian.h> 35441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <error.h> 36441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <fcntl.h> 37441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <gelf.h> 38441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <inttypes.h> 39441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <libintl.h> 40441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <locale.h> 41441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdbool.h> 42441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <stdlib.h> 43441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <string.h> 44441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <unistd.h> 45441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <sys/param.h> 46441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 47441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <elf-knowledge.h> 48441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#include <system.h> 49cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libelf/libelfP.h" 50cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libelf/common.h" 51cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libebl/libeblP.h" 52cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libdw/libdwP.h" 53cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libdwfl/libdwflP.h" 54cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libdw/memory-access.h" 55441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 56441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 57441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Name and version of program. */ 58441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void print_version (FILE *stream, struct argp_state *state); 59441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectvoid (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; 60441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 61cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Bug report address. */ 62cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengconst char *argp_program_bug_address = PACKAGE_BUGREPORT; 63441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 64441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define ARGP_strict 300 65441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define ARGP_gnuld 301 66441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 67441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Definitions of arguments for argp functions. */ 68441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct argp_option options[] = 69441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 70441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 71441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { "strict", ARGP_strict, NULL, 0, 72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng N_("Be extremely strict, flag level 2 features."), 0 }, 73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 }, 74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "debuginfo", 'd', NULL, 0, N_("Binary is a separate debuginfo file"), 0 }, 75441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { "gnu-ld", ARGP_gnuld, NULL, 0, 76441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project N_("Binary has been created with GNU ld and is therefore known to be \ 77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengbroken in certain ways"), 0 }, 78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { NULL, 0, NULL, 0, NULL, 0 } 79441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}; 80441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 81441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Short description of program. */ 82441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char doc[] = N_("\ 83441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectPedantic checking of ELF files compliance with gABI/psABI spec."); 84441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 85441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Strings for arguments in help texts. */ 86441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char args_doc[] = N_("FILE..."); 87441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 88441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Prototype for option handler. */ 89441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic error_t parse_opt (int key, char *arg, struct argp_state *state); 90441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 91441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Data structure to communicate with argp functions. */ 92441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic struct argp argp = 93441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 94cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng options, parse_opt, args_doc, doc, NULL, NULL, NULL 95441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project}; 96441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 97441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 98441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Declarations of local functions. */ 99441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void process_file (int fd, Elf *elf, const char *prefix, 100441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project const char *suffix, const char *fname, size_t size, 101441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project bool only_one); 102441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void process_elf_file (Elf *elf, const char *prefix, const char *suffix, 103441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project const char *fname, size_t size, bool only_one); 104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void check_note_section (Ebl *ebl, GElf_Ehdr *ehdr, 105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr, int idx); 106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 107441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 108441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Report an error. */ 109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define ERROR(str, args...) \ 110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project do { \ 111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project printf (str, ##args); \ 112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ++error_count; \ 113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } while (0) 114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic unsigned int error_count; 115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if we should perform very strict testing. */ 117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool be_strict; 118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if no message is to be printed if the run is succesful. */ 120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool be_quiet; 121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* True if binary is from strip -f, not a normal ELF file. */ 123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool is_debuginfo; 124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* True if binary is assumed to be generated with GNU ld. */ 126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool gnuld; 127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Index of section header string table. */ 129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic uint32_t shstrndx; 130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Array to count references in section groups. */ 132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int *scnref; 133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 135441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectint 136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmain (int argc, char *argv[]) 137441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Set locale. */ 139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project setlocale (LC_ALL, ""); 140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Initialize the message catalog. */ 142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng textdomain (PACKAGE_TARNAME); 143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Parse and process arguments. */ 145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int remaining; 146441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project argp_parse (&argp, argc, argv, 0, &remaining, NULL); 147441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 148441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Before we start tell the ELF library which version we are using. */ 149441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project elf_version (EV_CURRENT); 150441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 151441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Now process all the files given at the command line. */ 152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool only_one = remaining + 1 == argc; 153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project do 154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Open the file. */ 156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int fd = open (argv[remaining], O_RDONLY); 157441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (fd == -1) 158441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project error (0, errno, gettext ("cannot open input file")); 160441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 161441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 162441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Create an `Elf' descriptor. */ 164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); 165441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (elf == NULL) 166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("cannot generate Elf descriptor: %s\n"), 167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project elf_errmsg (-1)); 168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project unsigned int prev_error_count = error_count; 171441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project struct stat64 st; 172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (fstat64 (fd, &st) != 0) 174441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project printf ("cannot stat '%s': %m\n", argv[remaining]); 176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project close (fd); 177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project process_file (fd, elf, NULL, NULL, argv[remaining], st.st_size, 181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project only_one); 182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Now we can close the descriptor. */ 184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (elf_end (elf) != 0) 185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("error while closing Elf descriptor: %s\n"), 186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project elf_errmsg (-1)); 187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (prev_error_count == error_count && !be_quiet) 189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project puts (gettext ("No errors")); 190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project close (fd); 193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project while (++remaining < argc); 195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return error_count != 0; 197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Handle program arguments. */ 201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic error_t 202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengparse_opt (int key, char *arg __attribute__ ((unused)), 203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct argp_state *state __attribute__ ((unused))) 204441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 205441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project switch (key) 206441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 207441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case ARGP_strict: 208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project be_strict = true; 209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case 'q': 212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project be_quiet = true; 213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 'd': 216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng is_debuginfo = true; 217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case ARGP_gnuld: 219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project gnuld = true; 220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case ARGP_KEY_NO_ARGS: 223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fputs (gettext ("Missing file name.\n"), stderr); 224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR, 225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng program_invocation_short_name); 226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exit (1); 227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project default: 229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return ARGP_ERR_UNKNOWN; 230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return 0; 232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Print the version information. */ 236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fprintf (stream, "elflint (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project fprintf (stream, gettext ("\ 241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectCopyright (C) %s Red Hat, Inc.\n\ 242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source ProjectThis is free software; see the source for copying conditions. There is NO\n\ 243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng"), "2008"); 245441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); 246441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 247441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Process one file. */ 250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 251441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprocess_file (int fd, Elf *elf, const char *prefix, const char *suffix, 252441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project const char *fname, size_t size, bool only_one) 253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 254441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* We can handle two types of files: ELF files and archives. */ 255441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf_Kind kind = elf_kind (elf); 256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project switch (kind) 258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 259441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case ELF_K_ELF: 260441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Yes! It's an ELF file. */ 261441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project process_elf_file (elf, prefix, suffix, fname, size, only_one); 262441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 263441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 264441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case ELF_K_AR: 265441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 266441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf *subelf; 267441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf_Cmd cmd = ELF_C_READ_MMAP; 268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project size_t prefix_len = prefix == NULL ? 0 : strlen (prefix); 269441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project size_t fname_len = strlen (fname) + 1; 270441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char new_prefix[prefix_len + 1 + fname_len]; 271441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char new_suffix[(suffix == NULL ? 0 : strlen (suffix)) + 2]; 272441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char *cp = new_prefix; 273441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Create the full name of the file. */ 275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (prefix != NULL) 276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 277441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cp = mempcpy (cp, prefix, prefix_len); 278441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project *cp++ = '('; 279441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project strcpy (stpcpy (new_suffix, suffix), ")"); 280441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 281441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 282441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project new_suffix[0] = '\0'; 283441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project memcpy (cp, fname, fname_len); 284441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 285441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* It's an archive. We process each file in it. */ 286441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project while ((subelf = elf_begin (fd, cmd, elf)) != NULL) 287441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 288441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project kind = elf_kind (subelf); 289441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 290441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Call this function recursively. */ 291441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (kind == ELF_K_ELF || kind == ELF_K_AR) 292441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 293441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf_Arhdr *arhdr = elf_getarhdr (subelf); 294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project assert (arhdr != NULL); 295441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 296441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project process_file (fd, subelf, new_prefix, new_suffix, 297441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project arhdr->ar_name, arhdr->ar_size, false); 298441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 299441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Get next archive element. */ 301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cmd = elf_next (subelf); 302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (elf_end (subelf) != 0) 303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext (" error while freeing sub-ELF descriptor: %s\n"), 304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project elf_errmsg (-1)); 305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 309441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project default: 310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* We cannot do anything. */ 311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengNot an ELF file - it has the wrong magic bytes at the start\n")); 313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const char * 319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection_name (Ebl *ebl, int idx) 320441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr shdr_mem; 322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr *shdr; 323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem); 325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return elf_strptr (ebl->elf, shstrndx, shdr->sh_name); 327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const int valid_e_machine[] = 331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 332441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EM_M32, EM_SPARC, EM_386, EM_68K, EM_88K, EM_860, EM_MIPS, EM_S370, 333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EM_MIPS_RS3_LE, EM_PARISC, EM_VPP500, EM_SPARC32PLUS, EM_960, EM_PPC, 334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EM_PPC64, EM_S390, EM_V800, EM_FR20, EM_RH32, EM_RCE, EM_ARM, 335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EM_FAKE_ALPHA, EM_SH, EM_SPARCV9, EM_TRICORE, EM_ARC, EM_H8_300, 336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE, 337441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16, 338441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7, 339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX, 340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM, 341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300, 342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA 343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project }; 344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define nvalid_e_machine \ 345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project (sizeof (valid_e_machine) / sizeof (valid_e_machine[0])) 346441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 347441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 348441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Number of sections. */ 349441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic unsigned int shnum; 350441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 351441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size) 354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char buf[512]; 356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project size_t cnt; 357441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check e_ident field. */ 359441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ident[EI_MAG0] != ELFMAG0) 360441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR ("e_ident[%d] != '%c'\n", EI_MAG0, ELFMAG0); 361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ident[EI_MAG1] != ELFMAG1) 362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR ("e_ident[%d] != '%c'\n", EI_MAG1, ELFMAG1); 363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ident[EI_MAG2] != ELFMAG2) 364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR ("e_ident[%d] != '%c'\n", EI_MAG2, ELFMAG2); 365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ident[EI_MAG3] != ELFMAG3) 366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR ("e_ident[%d] != '%c'\n", EI_MAG3, ELFMAG3); 367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ident[EI_CLASS] != ELFCLASS32 369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && ehdr->e_ident[EI_CLASS] != ELFCLASS64) 370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("e_ident[%d] == %d is no known class\n"), 371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EI_CLASS, ehdr->e_ident[EI_CLASS]); 372441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB 374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && ehdr->e_ident[EI_DATA] != ELFDATA2MSB) 375441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("e_ident[%d] == %d is no known data encoding\n"), 376441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EI_DATA, ehdr->e_ident[EI_DATA]); 377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) 379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("unknown ELF header version number e_ident[%d] == %d\n"), 380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EI_VERSION, ehdr->e_ident[EI_VERSION]); 381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* We currently don't handle any OS ABIs. */ 383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE) 384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("unsupported OS ABI e_ident[%d] == '%s'\n"), 385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EI_OSABI, 386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf))); 387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* No ABI versions other than zero supported either. */ 389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ident[EI_ABIVERSION] != 0) 390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("unsupport ABI version e_ident[%d] == %d\n"), 391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]); 392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt) 394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ident[cnt] != 0) 395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("e_ident[%zu] is not zero\n"), cnt); 396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check the e_type field. */ 398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC 399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE) 400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("unknown object file type %d\n"), ehdr->e_type); 401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check the e_machine field. */ 403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (cnt = 0; cnt < nvalid_e_machine; ++cnt) 404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (valid_e_machine[cnt] == ehdr->e_machine) 405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (cnt == nvalid_e_machine) 407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("unknown machine type %d\n"), ehdr->e_machine); 408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check the e_version field. */ 410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_version != EV_CURRENT) 411441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("unknown object file version\n")); 412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 413441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check the e_phoff and e_phnum fields. */ 414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_phoff == 0) 415441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 416441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_phnum != 0) 417441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid program header offset\n")); 418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN) 419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectexecutables and DSOs cannot have zero program header offset\n")); 421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (ehdr->e_phnum == 0) 423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid number of program header entries\n")); 424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check the e_shoff field. */ 426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project shnum = ehdr->e_shnum; 427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project shstrndx = ehdr->e_shstrndx; 428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_shoff == 0) 429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_shnum != 0) 431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid section header table offset\n")); 432441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN 433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && ehdr->e_type != ET_CORE) 434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section header table must be present\n")); 435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 436441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_shnum == 0) 439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Get the header of the zeroth section. The sh_size field 441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project might contain the section number. */ 442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr shdr_mem; 443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 444441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr != NULL) 445441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 446441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* The error will be reported later. */ 447441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_size == 0) 448441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 449441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectinvalid number of section header table entries\n")); 450441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 451441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project shnum = shdr->sh_size; 452441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 453441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 454441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 455441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_shstrndx == SHN_XINDEX) 456441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Get the header of the zeroth section. The sh_size field 458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project might contain the section number. */ 459441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr shdr_mem; 460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr != NULL && shdr->sh_link < shnum) 462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shstrndx = shdr->sh_link; 463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 464441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (shstrndx >= shnum) 465441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid section header index\n")); 466441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 467441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 468441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check the e_flags field. */ 469441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (!ebl_machine_flag_check (ebl, ehdr->e_flags)) 470441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid machine flags: %s\n"), 471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf))); 472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check e_ehsize, e_phentsize, and e_shentsize fields. */ 474441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (gelf_getclass (ebl->elf) == ELFCLASS32) 475441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 476441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr)) 477441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize); 478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr)) 480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid program header size: %hd\n"), 481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ehdr->e_phentsize); 482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size) 483441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid program header position or size\n")); 484441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr)) 486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid section header size: %hd\n"), 487441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ehdr->e_shentsize); 488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size) 489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid section header position or size\n")); 490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (gelf_getclass (ebl->elf) == ELFCLASS64) 492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr)) 494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize); 495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr)) 497441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid program header size: %hd\n"), 498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ehdr->e_phentsize); 499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size) 500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid program header position or size\n")); 501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr)) 503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid section header size: %hd\n"), 504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ehdr->e_shentsize); 505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size) 506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("invalid section header position or size\n")); 507441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Check that there is a section group section with index < IDX which 512441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project contains section IDX and that there is exactly one. */ 513441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_scn_group (Ebl *ebl, int idx) 515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (scnref[idx] == 0) 517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* No reference so far. Search following sections, maybe the 519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project order is wrong. */ 520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project size_t cnt; 521441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 522441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (cnt = idx + 1; cnt < shnum; ++cnt) 523441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = elf_getscn (ebl->elf, cnt); 525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr shdr_mem; 526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr == NULL) 528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* We cannot get the section header so we cannot check it. 529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project The error to get the section header will be shown 530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project somewhere else. */ 531441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 532441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_type != SHT_GROUP) 534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (scn, NULL); 537441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (data == NULL || data->d_size < sizeof (Elf32_Word)) 538441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Cannot check the section. */ 539441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word *grpdata = (Elf32_Word *) data->d_buf; 542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word); 543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++inner) 544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (grpdata[inner] == (Elf32_Word) idx) 545441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project goto out; 546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project out: 549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (cnt == shnum) 550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 551441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"), 552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 554441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 555441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section group [%2zu] '%s' does not preceed group member\n"), 556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_symtab (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project bool no_xndx_warned = false; 566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int no_pt_tls = 0; 567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (data == NULL) 569441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return; 573441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr strshdr_mem; 576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &strshdr_mem); 578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strshdr == NULL) 579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 581441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (strshdr->sh_type != SHT_STRTAB) 582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"), 584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_link, section_name (ebl, shdr->sh_link), 585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng strshdr = NULL; 587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 588441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 589441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Search for an extended section index table section. */ 590441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf_Data *xndxdata = NULL; 591441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf32_Word xndxscnidx = 0; 592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool found_xndx = false; 593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t cnt = 1; cnt < shnum; ++cnt) 594441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (cnt != (size_t) idx) 595441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt); 597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr xndxshdr_mem; 598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem); 599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (xndxshdr == NULL) 600441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 601441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 602441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX 603441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && xndxshdr->sh_link == (GElf_Word) idx) 604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (found_xndx) 606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': symbol table cannot have more than one extended index section\n"), 608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng xndxdata = elf_getdata (xndxscn, NULL); 611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng xndxscnidx = elf_ndxscn (xndxscn); 612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng found_xndx = true; 613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 614441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 615441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 616441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)) 617441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2u] '%s': entry size is does not match ElfXX_Sym\n"), 619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 620441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Test the zeroth entry. */ 622441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Sym sym_mem; 623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf32_Word xndx; 624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx); 625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym == NULL) 626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': cannot get symbol %d: %s\n"), 627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 0, elf_errmsg (-1)); 628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym->st_name != 0) 631441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "st_name"); 633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym->st_value != 0) 634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "st_value"); 636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym->st_size != 0) 637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "st_size"); 639441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym->st_info != 0) 640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "st_info"); 642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym->st_other != 0) 643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "st_other"); 645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym->st_shndx != 0) 646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"), 647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "st_shndx"); 648441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (xndxdata != NULL && xndx != 0) 649441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 650441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': XINDEX for zeroth entry not zero\n"), 651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng xndxscnidx, section_name (ebl, xndxscnidx)); 652441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 653441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t cnt = 1; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 655441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 656441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx); 657441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym == NULL) 658441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 659441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': cannot get symbol %zu: %s\n"), 660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, elf_errmsg (-1)); 661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 664441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project const char *name = NULL; 665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strshdr == NULL) 666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name = ""; 667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (sym->st_name >= strshdr->sh_size) 668441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 669441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: invalid name value\n"), 670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name); 674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project assert (name != NULL); 675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 677441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym->st_shndx == SHN_XINDEX) 678441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 679441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (xndxdata == NULL) 680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: too large section index but no extended section index section\n"), 683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project no_xndx_warned = true; 685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 686441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (xndx < SHN_LORESERVE) 687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 688441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"), 689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng xndxscnidx, section_name (ebl, xndxscnidx), cnt, 690441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project xndx); 691441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if ((sym->st_shndx >= SHN_LORESERVE 693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project // && sym->st_shndx <= SHN_HIRESERVE always true 694441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && sym->st_shndx != SHN_ABS 695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && sym->st_shndx != SHN_COMMON) 696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project || (sym->st_shndx >= shnum 697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && (sym->st_shndx < SHN_LORESERVE 698441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* || sym->st_shndx > SHN_HIRESERVE always false */))) 699441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 700441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: invalid section index\n"), 701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 703441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project xndx = sym->st_shndx; 704441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (GELF_ST_TYPE (sym->st_info) >= STT_NUM 706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), NULL, 0)) 707441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': symbol %zu: unknown type\n"), 708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 709441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 710441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (GELF_ST_BIND (sym->st_info) >= STB_NUM) 711441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 712441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: unknown symbol binding\n"), 713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 714441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 715441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (xndx == SHN_COMMON) 716441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 717441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Common symbols can only appear in relocatable files. */ 718441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_type != ET_REL) 719441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 720441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n"), 721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 722441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (cnt < shdr->sh_info) 723441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 724441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n"), 725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (GELF_R_TYPE (sym->st_info) == STT_FUNC) 727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"), 729cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (xndx > 0 && xndx < shnum) 732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr destshdr_mem; 734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr *destshdr; 735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem); 737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (destshdr != NULL) 738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 739cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr sh_addr = (ehdr->e_type == ET_REL ? 0 740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng : destshdr->sh_addr); 741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (GELF_ST_TYPE (sym->st_info) != STT_TLS) 742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 743cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (! ebl_check_special_symbol (ebl, ehdr, sym, name, 744cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng destshdr)) 745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym->st_value - sh_addr > destshdr->sh_size) 747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* GNU ld has severe bugs. When it decides to remove 749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng empty sections it leaves symbols referencing them 750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng behind. These are symbols in .symtab. */ 751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!gnuld 752cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || strcmp (section_name (ebl, idx), ".symtab") 753cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (strcmp (name, "__preinit_array_start") != 0 754cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && strcmp (name, "__preinit_array_end") != 0 755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && strcmp (name, "__init_array_start") != 0 756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && strcmp (name, "__init_array_end") != 0 757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && strcmp (name, "__fini_array_start") != 0 758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && strcmp (name, "__fini_array_end") != 0)) 759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: st_value out of bounds\n"), 761cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 762cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if ((sym->st_value - sh_addr 764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + sym->st_size) > destshdr->sh_size) 765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"), 767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) xndx, section_name (ebl, xndx)); 769cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 772441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((destshdr->sh_flags & SHF_TLS) == 0) 774441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_TLS flag set\n"), 776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 777cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) xndx, section_name (ebl, xndx)); 778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_type == ET_REL) 780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 781441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* For object files the symbol value must fall 782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project into the section. */ 783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym->st_value > destshdr->sh_size) 784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"), 786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) xndx, section_name (ebl, xndx)); 788441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (sym->st_value + sym->st_size 789441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project > destshdr->sh_size) 790441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 791441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"), 792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) xndx, section_name (ebl, xndx)); 794441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 795441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 796441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 797441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Phdr phdr_mem; 798441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Phdr *phdr = NULL; 799441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int pcnt; 800441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 801441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt) 802441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 803441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem); 804441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (phdr != NULL && phdr->p_type == PT_TLS) 805441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 806441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 807441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 808441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (pcnt == ehdr->e_phnum) 809441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 810441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (no_pt_tls++ == 0) 811441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 812441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"), 813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 814441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 816441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 817441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym->st_value 818441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project < destshdr->sh_offset - phdr->p_offset) 819441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 820441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"), 821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) xndx, section_name (ebl, xndx)); 823441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (sym->st_value 824441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project > (destshdr->sh_offset - phdr->p_offset 825441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project + destshdr->sh_size)) 826441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 827441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"), 828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) xndx, section_name (ebl, xndx)); 830441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (sym->st_value + sym->st_size 831441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project > (destshdr->sh_offset - phdr->p_offset 832441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project + destshdr->sh_size)) 833441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 834441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"), 835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) xndx, section_name (ebl, xndx)); 837441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 838441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 839441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 840441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 841441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 842441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 843441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (GELF_ST_BIND (sym->st_info) == STB_LOCAL) 844441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 845441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (cnt >= shdr->sh_info) 846441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 847441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: local symbol outside range described in sh_info\n"), 848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 849441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 850441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 851441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 852441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (cnt < shdr->sh_info) 853441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 854441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: non-local symbol outside range described in sh_info\n"), 855cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 856441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 857441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 858441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (GELF_ST_TYPE (sym->st_info) == STT_SECTION 859441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && GELF_ST_BIND (sym->st_info) != STB_LOCAL) 860441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 861441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': symbol %zu: non-local section symbol\n"), 862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 863441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 864441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (name != NULL) 865441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0) 867441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 868cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that address and size match the global offset table. */ 869cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr destshdr_mem; 871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), 872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &destshdr_mem); 873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 874cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (destshdr == NULL && xndx == SHN_ABS) 875cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* In a DSO, we have to find the GOT section by name. */ 877cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *gotscn = NULL; 878cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *gscn = NULL; 879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL) 880cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 881cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng destshdr = gelf_getshdr (gscn, &destshdr_mem); 882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (destshdr != NULL); 883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *sname = elf_strptr (ebl->elf, 884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ehdr->e_shstrndx, 885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng destshdr->sh_name); 886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sname != NULL) 887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strcmp (sname, ".got.plt") == 0) 889cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 890cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strcmp (sname, ".got") == 0) 891cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Do not stop looking. 892cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng There might be a .got.plt section. */ 893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gotscn = gscn; 894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng destshdr = NULL; 897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 898441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (destshdr == NULL && gotscn != NULL) 900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng destshdr = gelf_getshdr (gotscn, &destshdr_mem); 901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *sname = ((destshdr == NULL || xndx == SHN_UNDEF) 904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? NULL 905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng : elf_strptr (ebl->elf, ehdr->e_shstrndx, 906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng destshdr->sh_name)); 907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sname == NULL) 908441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 909cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (xndx != SHN_UNDEF || ehdr->e_type != ET_REL) 910cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \ 912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengbad section [%2d]\n"), 913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), xndx); 914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (strcmp (sname, ".got.plt") != 0 916cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && strcmp (sname, ".got") != 0) 917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \ 919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s'\n"), 920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), xndx, sname); 921441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (destshdr != NULL) 923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Found it. */ 925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!ebl_check_special_symbol (ebl, ehdr, sym, name, 926cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng destshdr)) 927441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 928cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr->e_type != ET_REL 929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && sym->st_value != destshdr->sh_addr) 930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* This test is more strict than the psABIs which 931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng usually allow the symbol to be in the middle of 932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the .got section, allowing negative offsets. */ 933441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"), 935cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 936441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project (uint64_t) sym->st_value, 937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sname, (uint64_t) destshdr->sh_addr); 938441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!gnuld && sym->st_size != destshdr->sh_size) 940441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"), 942cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 943441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project (uint64_t) sym->st_size, 944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sname, (uint64_t) destshdr->sh_size); 945441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 946441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 948441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 949441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"), 950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 951441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 952441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (strcmp (name, "_DYNAMIC") == 0) 953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that address and size match the dynamic section. 954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng We locate the dynamic section via the program header 955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng entry. */ 956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt) 957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr_mem; 959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem); 960441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr != NULL && phdr->p_type == PT_DYNAMIC) 962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym->st_value != phdr->p_vaddr) 964cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 965441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"), 966cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 967cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint64_t) sym->st_value, 968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint64_t) phdr->p_vaddr); 969441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!gnuld && sym->st_size != phdr->p_memsz) 971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 972441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"), 973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint64_t) sym->st_size, 975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint64_t) phdr->p_memsz); 976441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 979441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 980441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 981441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 982441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 983441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 984441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 985441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool 986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengis_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr, 987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool is_rela) 988441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 989441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* If this is no executable or DSO it cannot be a .rel.dyn section. */ 990441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 991441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return false; 992441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 993441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check the section name. Unfortunately necessary. */ 994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strcmp (section_name (ebl, idx), is_rela ? ".rela.dyn" : ".rel.dyn")) 995441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return false; 996441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 997441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section 998441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project entry can be present as well. */ 999441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf_Scn *scn = NULL; 1000441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 1001441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1002441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr rcshdr_mem; 1003441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem); 1004441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project assert (rcshdr != NULL); 1005441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1006441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (rcshdr->sh_type == SHT_DYNAMIC) 1007441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1008441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Found the dynamic section. Look through it. */ 1009441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf_Data *d = elf_getdata (scn, NULL); 1010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t cnt; 1011441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1012441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt) 1013441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1014441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Dyn dyn_mem; 1015441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem); 1016441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project assert (dyn != NULL); 1017441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1018441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (dyn->d_tag == DT_RELCOUNT) 1019441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Found it. Does the type match. */ 1021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (is_rela) 1022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': DT_RELCOUNT used for this RELA section\n"), 1024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1026cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Does the number specified number of relative 1028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relocations exceed the total number of 1029cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relocations? */ 1030cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize) 1031cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1032cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"), 1033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) dyn->d_un.d_val); 1035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure the specified number of relocations are 1037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relative. */ 1038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf, 1039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx), NULL); 1040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (reldata != NULL) 1041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t inner = 0; 1042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inner < shdr->sh_size / shdr->sh_entsize; 1043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++inner) 1044cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel rel_mem; 1046cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel *rel = gelf_getrel (reldata, inner, 1047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &rel_mem); 1048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (rel == NULL) 1049cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The problem will be reported elsewhere. */ 1050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1051cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ebl_relative_reloc_p (ebl, 1053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GELF_R_TYPE (rel->r_info))) 1054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (inner >= dyn->d_un.d_val) 1056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"), 1058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) dyn->d_un.d_val); 1060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (inner < dyn->d_un.d_val) 1062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"), 1064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1065cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inner, (int) dyn->d_un.d_val); 1066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1070cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dyn->d_tag == DT_RELACOUNT) 1071cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1072cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Found it. Does the type match. */ 1073cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!is_rela) 1074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1075cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': DT_RELACOUNT used for this REL section\n"), 1076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1077cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Does the number specified number of relative 1080cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relocations exceed the total number of 1081cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relocations? */ 1082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize) 1083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1084441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"), 1085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) dyn->d_un.d_val); 1087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure the specified number of relocations are 1089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relative. */ 1090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf, 1091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx), NULL); 1092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (reldata != NULL) 1093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t inner = 0; 1094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inner < shdr->sh_size / shdr->sh_entsize; 1095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++inner) 1096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela rela_mem; 1098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela *rela = gelf_getrela (reldata, inner, 1099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &rela_mem); 1100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (rela == NULL) 1101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The problem will be reported elsewhere. */ 1102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ebl_relative_reloc_p (ebl, 1105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GELF_R_TYPE (rela->r_info))) 1106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (inner >= dyn->d_un.d_val) 1108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"), 1110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) dyn->d_un.d_val); 1112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (inner < dyn->d_un.d_val) 1114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"), 1116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inner, (int) dyn->d_un.d_val); 1118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1123441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 1124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return true; 1128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 1129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct loaded_segment 1132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 1133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr from; 1134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr to; 1135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool read_only; 1136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct loaded_segment *next; 1137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 1138441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Check whether binary has text relocation flag set. */ 1141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool textrel; 1142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Keep track of whether text relocation flag is needed. */ 1144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool needed_textrel; 1145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool 1148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr, 1149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int idx, int reltype, GElf_Shdr **destshdrp, 1150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp) 1151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool reldyn = false; 1153441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1154441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check whether the link to the section we relocate is reasonable. */ 1155441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_info >= shnum) 1156441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"), 1157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (shdr->sh_info != 0) 1159441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *destshdrp = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info), 1161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng destshdr_memp); 1162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*destshdrp != NULL) 1163441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if((*destshdrp)->sh_type != SHT_PROGBITS 1165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (*destshdrp)->sh_type != SHT_NOBITS) 1166441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1167441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true); 1168441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (!reldyn) 1169441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1170441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': invalid destination section type\n"), 1171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1172441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 1173441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* There is no standard, but we require that .rel{,a}.dyn 1175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project sections have a sh_info value of zero. */ 1176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_info != 0) 1177441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1178441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': sh_info should be zero\n"), 1179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (((*destshdrp)->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0) 1184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': no relocations for merge-able sections possible\n"), 1186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_entsize != gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT)) 1191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext (reltype == ELF_T_RELA ? "\ 1192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\ 1193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': section entry size does not match ElfXX_Rel\n"), 1194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* In preparation of checking whether relocations are text 1197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relocations or not we need to determine whether the file is 1198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng flagged to have text relocation and we need to determine a) what 1199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the loaded segments are and b) which are read-only. This will 1200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng also allow us to determine whether the same reloc section is 1201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng modifying loaded and not loaded segments. */ 1202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int i = 0; i < ehdr->e_phnum; ++i) 1203441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr_mem; 1205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem); 1206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr == NULL) 1207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1208441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr->p_type == PT_LOAD) 1210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct loaded_segment *newp = xmalloc (sizeof (*newp)); 1212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newp->from = phdr->p_vaddr; 1213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newp->to = phdr->p_vaddr + phdr->p_memsz; 1214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newp->read_only = (phdr->p_flags & PF_W) == 0; 1215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newp->next = *loadedp; 1216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *loadedp = newp; 1217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (phdr->p_type == PT_DYNAMIC) 1219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset); 1221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr dynshdr_mem; 1222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem); 1223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *dyndata = elf_getdata (dynscn, NULL); 1224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC 1225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && dyndata != NULL) 1226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j) 1227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Dyn dyn_mem; 1229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem); 1230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dyn != NULL 1231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (dyn->d_tag == DT_TEXTREL 1232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (dyn->d_tag == DT_FLAGS 1233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (dyn->d_un.d_val & DF_TEXTREL) != 0))) 1234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng textrel = true; 1236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* A quick test which can be easily done here (although it is a bit 1243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng out of place): the text relocation flag makes only sense if there 1244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng is a segment which is not writable. */ 1245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (textrel) 1246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct loaded_segment *seg = *loadedp; 1248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (seg != NULL && !seg->read_only) 1249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng seg = seg->next; 1250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (seg == NULL) 1251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengtext relocation flag set but there is no read-only segment\n")); 1253441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return reldyn; 1256441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 1257441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1258441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengenum load_state 1260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng state_undecided, 1262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng state_loaded, 1263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng state_unloaded, 1264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng state_error 1265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 1266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1268441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 1269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_one_reloc (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *relshdr, int idx, 1270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t cnt, const GElf_Shdr *symshdr, Elf_Data *symdata, 1271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr r_offset, GElf_Xword r_info, 1272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const GElf_Shdr *destshdr, bool reldyn, 1273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct loaded_segment *loaded, enum load_state *statep) 1274441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 1275441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project bool known_broken = gnuld; 1276441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (r_info))) 1278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"), 1279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 1280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 1281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The executable/DSO can contain relocation sections with 1282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng all the relocations the linker has applied. Those sections 1283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng are marked non-loaded, though. */ 1284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (relshdr->sh_flags & SHF_ALLOC) != 0) 1285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !ebl_reloc_valid_use (ebl, GELF_R_TYPE (r_info))) 1286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"), 1288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 1289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symshdr != NULL 1291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ((GELF_R_SYM (r_info) + 1) 1292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT) 1293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng > symshdr->sh_size)) 1294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': relocation %zu: invalid symbol index\n"), 1296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 1297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* No more tests if this is a no-op relocation. */ 1299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info))) 1300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return; 1301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info))) 1303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name; 1305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char buf[64]; 1306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_mem; 1307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem); 1308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym != NULL 1309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Get the name for the symbol. */ 1310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)) 1311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 ) 1312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"), 1314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 1315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ebl_reloc_type_name (ebl, GELF_R_SYM (r_info), 1316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng buf, sizeof (buf))); 1317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (reldyn) 1320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng // XXX TODO Check .rel.dyn section addresses. 1322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (!known_broken) 1324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (destshdr != NULL 1326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && GELF_R_TYPE (r_info) != 0 1327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (r_offset - (ehdr->e_type == ET_REL ? 0 1328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng : destshdr->sh_addr)) >= destshdr->sh_size) 1329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': relocation %zu: offset out of bounds\n"), 1331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 1332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_mem; 1335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem); 1336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info)) 1338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure the referenced symbol is an object or unspecified. */ 1339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && sym != NULL 1340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE 1341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && GELF_ST_TYPE (sym->st_info) != STT_OBJECT) 1342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char buf[64]; 1344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"), 1345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 1346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), 1347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng buf, sizeof (buf))); 1348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 1351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (relshdr->sh_flags & SHF_ALLOC) != 0) 1352441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool in_loaded_seg = false; 1354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (loaded != NULL) 1355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r_offset < loaded->to 1357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from) 1358441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The symbol is in this segment. */ 1360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (loaded->read_only) 1361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (textrel) 1363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed_textrel = true; 1364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"), 1366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 1367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng in_loaded_seg = true; 1370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng loaded = loaded->next; 1373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*statep == state_undecided) 1376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *statep = in_loaded_seg ? state_loaded : state_unloaded; 1377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if ((*statep == state_unloaded && in_loaded_seg) 1378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (*statep == state_loaded && !in_loaded_seg)) 1379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': relocations are against loaded and unloaded data\n"), 1382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *statep = state_error; 1384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 1390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 1391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 1393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 1394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 1396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 1398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check the fields of the section header. */ 1401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr destshdr_mem; 1402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *destshdr = NULL; 1403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct loaded_segment *loaded = NULL; 1404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr, 1405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &destshdr_mem, &loaded); 1406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1407441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 1408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr symshdr_mem; 1409441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 1410441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf_Data *symdata = elf_getdata (symscn, NULL); 1411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng enum load_state state = state_undecided; 1412441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 1414441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela rela_mem; 1416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem); 1417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (rela == NULL) 1418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': cannot get relocation %zu: %s\n"), 1421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, elf_errmsg (-1)); 1422441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 1423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata, 1426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng rela->r_offset, rela->r_info, destshdr, reldyn, loaded, 1427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &state); 1428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (loaded != NULL) 1431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct loaded_segment *old = loaded; 1433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng loaded = loaded->next; 1434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (old); 1435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 1440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 1441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 1443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 1444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 1446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 1448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check the fields of the section header. */ 1451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr destshdr_mem; 1452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *destshdr = NULL; 1453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct loaded_segment *loaded = NULL; 1454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr, 1455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &destshdr_mem, &loaded); 1456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 1458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr symshdr_mem; 1459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 1460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symdata = elf_getdata (symscn, NULL); 1461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng enum load_state state = state_undecided; 1462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 1464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel rel_mem; 1466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem); 1467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (rel == NULL) 1468441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': cannot get relocation %zu: %s\n"), 1471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, elf_errmsg (-1)); 1472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 1473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata, 1476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng rel->r_offset, rel->r_info, destshdr, reldyn, loaded, 1477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &state); 1478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (loaded != NULL) 1481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct loaded_segment *old = loaded; 1483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng loaded = loaded->next; 1484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (old); 1485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 1487441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Number of dynamic sections. */ 1490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic int ndynamic; 1491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 1494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 1495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 1496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf_Data *data; 1497441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr strshdr_mem; 1498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr *strshdr; 1499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project size_t cnt; 1500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project static const bool dependencies[DT_NUM][DT_NUM] = 1501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_NEEDED] = { [DT_STRTAB] = true }, 1503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_PLTRELSZ] = { [DT_JMPREL] = true }, 1504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_HASH] = { [DT_SYMTAB] = true }, 1505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_STRTAB] = { [DT_STRSZ] = true }, 1506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_SYMENT] = true }, 1507441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true }, 1508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_RELASZ] = { [DT_RELA] = true }, 1509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_RELAENT] = { [DT_RELA] = true }, 1510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_STRSZ] = { [DT_STRTAB] = true }, 1511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_SYMENT] = { [DT_SYMTAB] = true }, 1512441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_SONAME] = { [DT_STRTAB] = true }, 1513441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_RPATH] = { [DT_STRTAB] = true }, 1514441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true }, 1515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_RELSZ] = { [DT_REL] = true }, 1516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_RELENT] = { [DT_REL] = true }, 1517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true }, 1518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_RUNPATH] = { [DT_STRTAB] = true }, 1519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_PLTREL] = { [DT_JMPREL] = true }, 1520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project }; 1521441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project bool has_dt[DT_NUM]; 1522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool has_val_dt[DT_VALNUM]; 1523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool has_addr_dt[DT_ADDRNUM]; 1524441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project static const bool level2[DT_NUM] = 1525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1526441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_RPATH] = true, 1527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_SYMBOLIC] = true, 1528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_TEXTREL] = true, 1529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_BIND_NOW] = true 1530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project }; 1531441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project static const bool mandatory[DT_NUM] = 1532441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_NULL] = true, 1534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_STRTAB] = true, 1535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_SYMTAB] = true, 1536441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_STRSZ] = true, 1537441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project [DT_SYMENT] = true 1538441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project }; 1539441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Addr reladdr = 0; 1540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Word relsz = 0; 1541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Addr pltreladdr = 0; 1542441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Word pltrelsz = 0; 1543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project memset (has_dt, '\0', sizeof (has_dt)); 1545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memset (has_val_dt, '\0', sizeof (has_val_dt)); 1546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memset (has_addr_dt, '\0', sizeof (has_addr_dt)); 1547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (++ndynamic == 2) 1549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("more than one dynamic section present\n")); 1550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 1552441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (data == NULL) 1553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1554441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 1555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1556441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return; 1557441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem); 1560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB) 1561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"), 1563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_link, section_name (ebl, shdr->sh_link), 1564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT)) 1567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section entry size does not match ElfXX_Dyn\n"), 1569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1571441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_info != 0) 1572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"), 1573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1574441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1575441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project bool non_null_warned = false; 1576441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 1577441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1578441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Dyn dyn_mem; 1579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem); 1580441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (dyn == NULL) 1581441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1582441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1583441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': cannot get dynamic section entry %zu: %s\n"), 1584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, elf_errmsg (-1)); 1585441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 1586441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1587441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1588441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned) 1589441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1590441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1591441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"), 1592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1593441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project non_null_warned = true; 1594441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1595441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1596441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (!ebl_dynamic_tag_check (ebl, dyn->d_tag)) 1597441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': entry %zu: unknown tag\n"), 1598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 1599441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dyn->d_tag >= 0 && dyn->d_tag < DT_NUM) 1601441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1602441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (has_dt[dyn->d_tag] 1603441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && dyn->d_tag != DT_NEEDED 1604441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && dyn->d_tag != DT_NULL 1605441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && dyn->d_tag != DT_POSFLAG_1) 1606441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1607441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char buf[50]; 1608441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1609441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': entry %zu: more than one entry with tag %s\n"), 1610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 1611441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl_dynamic_tag_name (ebl, dyn->d_tag, 1612441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project buf, sizeof (buf))); 1613441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1614441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1615441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (be_strict && level2[dyn->d_tag]) 1616441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1617441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char buf[50]; 1618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1619441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': entry %zu: level 2 tag %s used\n"), 1620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 1621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl_dynamic_tag_name (ebl, dyn->d_tag, 1622441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project buf, sizeof (buf))); 1623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project has_dt[dyn->d_tag] = true; 1626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (dyn->d_tag <= DT_VALRNGHI 1628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM) 1629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng has_val_dt[DT_VALTAGIDX (dyn->d_tag)] = true; 1630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (dyn->d_tag <= DT_ADDRRNGHI 1631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM) 1632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng has_addr_dt[DT_ADDRTAGIDX (dyn->d_tag)] = true; 1633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL 1635441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && dyn->d_un.d_val != DT_RELA) 1636441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1637441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"), 1638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 1639441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1640441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (dyn->d_tag == DT_REL) 1641441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project reladdr = dyn->d_un.d_ptr; 1642441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (dyn->d_tag == DT_RELSZ) 1643441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project relsz = dyn->d_un.d_val; 1644441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (dyn->d_tag == DT_JMPREL) 1645441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project pltreladdr = dyn->d_un.d_ptr; 1646441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (dyn->d_tag == DT_PLTRELSZ) 1647441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project pltrelsz = dyn->d_un.d_val; 1648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that addresses for entries are in loaded segments. */ 1650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (dyn->d_tag) 1651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t n; 1653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_STRTAB: 1654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We require the referenced section is the same as the one 1655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng specified in sh_link. */ 1656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strshdr->sh_addr != dyn->d_un.d_val) 1657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '%s' referenced by sh_link\n"), 1660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 1661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_link, section_name (ebl, shdr->sh_link)); 1662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto check_addr; 1665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 1667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dyn->d_tag < DT_ADDRRNGLO || dyn->d_tag > DT_ADDRRNGHI) 1668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Value is no pointer. */ 1669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* FALLTHROUGH */ 1671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_AUXILIARY: 1673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_FILTER: 1674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_FINI: 1675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_FINI_ARRAY: 1676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_HASH: 1677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_INIT: 1678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_INIT_ARRAY: 1679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_JMPREL: 1680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_PLTGOT: 1681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_REL: 1682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_RELA: 1683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_SYMBOLIC: 1684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_SYMTAB: 1685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_VERDEF: 1686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_VERNEED: 1687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_VERSYM: 1688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_addr: 1689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (n = 0; n < ehdr->e_phnum; ++n) 1690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr_mem; 1692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem); 1693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr != NULL && phdr->p_type == PT_LOAD 1694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && phdr->p_vaddr <= dyn->d_un.d_ptr 1695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr) 1696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (n >= ehdr->e_phnum)) 1699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char buf[50]; 1701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %zu: %s value must point into loaded segment\n"), 1703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 1704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, 1705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sizeof (buf))); 1706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_NEEDED: 1710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_RPATH: 1711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_RUNPATH: 1712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DT_SONAME: 1713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dyn->d_un.d_ptr >= strshdr->sh_size) 1714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char buf[50]; 1716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %zu: %s value must be valid offset in section [%2d] '%s'\n"), 1718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, 1719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, 1720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sizeof (buf)), 1721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_link, section_name (ebl, shdr->sh_link)); 1722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 1724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1725441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (cnt = 1; cnt < DT_NUM; ++cnt) 1728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (has_dt[cnt]) 1729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1730cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int inner = 0; inner < DT_NUM; ++inner) 1731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (dependencies[cnt][inner] && ! has_dt[inner]) 1732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char buf1[50]; 1734441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char buf2[50]; 1735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': contains %s entry but not %s\n"), 1738cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)), 1740441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2))); 1741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 1744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1745441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (mandatory[cnt]) 1746441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1747441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char buf[50]; 1748441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1749441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': mandatory tag %s not present\n"), 1750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1751441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf))); 1752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure we have an hash table. */ 1756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!has_dt[DT_HASH] && !has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)]) 1757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': no hash section present\n"), 1759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1760cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1761cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The GNU-style hash table also needs a symbol table. */ 1762cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!has_dt[DT_HASH] && has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)] 1763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !has_dt[DT_SYMTAB]) 1764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': contains %s entry but not %s\n"), 1766cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng "DT_GNU_HASH", "DT_SYMTAB"); 1768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check the rel/rela tags. At least one group must be available. */ 1770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT]) 1771441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT])) 1772441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1773441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': not all of %s, %s, and %s are present\n"), 1774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1775441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project "DT_RELA", "DT_RELASZ", "DT_RELAENT"); 1776441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1777441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT]) 1778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT])) 1779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': not all of %s, %s, and %s are present\n"), 1781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project "DT_REL", "DT_RELSZ", "DT_RELENT"); 1783cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1784cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that all prelink sections are present if any of them is. */ 1785cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)] 1786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)]) 1787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)]) 1789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"), 1791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "DT_GNU_PRELINKED"); 1792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)]) 1793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': %s tag missing in DSO marked during prelinking\n"), 1795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "DT_CHECKSUM"); 1796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Only DSOs can be marked like this. */ 1798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr->e_type != ET_DYN) 1799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': non-DSO file marked as dependency during prelink\n"), 1801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1803cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)] 1805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)] 1806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)] 1807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)]) 1808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)]) 1810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': %s tag missing in prelinked executable\n"), 1812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "DT_GNU_CONFLICTSZ"); 1813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)]) 1814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1815cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': %s tag missing in prelinked executable\n"), 1816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "DT_GNU_LIBLISTSZ"); 1817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)]) 1818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': %s tag missing in prelinked executable\n"), 1820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "DT_GNU_CONFLICT"); 1821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)]) 1822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': %s tag missing in prelinked executable\n"), 1824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), "DT_GNU_LIBLIST"); 1825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1826441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 1827441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1828441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1829441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 1830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 1831441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 1832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr->e_type != ET_REL) 1833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': only relocatable files can have extended section index\n"), 1836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 1838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1839441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 1841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr symshdr_mem; 1842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 1843441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB) 1844441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1845441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': extended section index section not for symbol table\n"), 1846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symdata = elf_getdata (symscn, NULL); 1848441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (symdata == NULL) 1849441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("cannot get data for symbol section\n")); 1850441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1851441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_entsize != sizeof (Elf32_Word)) 1852441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1853441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': entry size does not match Elf32_Word\n"), 1854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1855441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1856441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (symshdr != NULL 1857441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && (shdr->sh_size / shdr->sh_entsize 1858441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project < symshdr->sh_size / symshdr->sh_entsize)) 1859441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1860441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': extended index table too small for symbol table\n"), 1861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1862441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1863441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_info != 0) 1864441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"), 1865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t cnt = idx + 1; cnt < shnum; ++cnt) 1868441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1869441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Shdr rshdr_mem; 1870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem); 1871441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX 1872441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && rshdr->sh_link == shdr->sh_link) 1873441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1874441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1875441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"), 1876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 1877cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 1878441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 1879441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1880441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1881441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 1883441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1884441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (*((Elf32_Word *) data->d_buf) != 0) 1885441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("symbol 0 should have zero extended section index\n")); 1886441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt) 1888441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1889441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt]; 1890441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1891441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (xndx != 0) 1892441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1893441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Sym sym_data; 1894441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data); 1895441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym == NULL) 1896441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1897441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("cannot get data for symbol %zu\n"), cnt); 1898441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 1899441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1900441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1901441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (sym->st_shndx != SHN_XINDEX) 1902441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1903441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectextended section index is %" PRIu32 " but symbol index is not XINDEX\n"), 1904441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project (uint32_t) xndx); 1905441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1906441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 1907441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 1908441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1909441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1910441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 1911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx, 1912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *symshdr) 1913441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 1914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0]; 1915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1]; 1916441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize) 1918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"), 1920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), (long int) shdr->sh_size, 1921cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (long int) ((2 + nbucket + nchain) * shdr->sh_entsize)); 1922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t maxidx = nchain; 1924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symshdr != NULL) 1926441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1927cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t symsize = symshdr->sh_size / symshdr->sh_entsize; 1928441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (nchain > symshdr->sh_size / symshdr->sh_entsize) 1930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': chain array too large\n"), 1931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1932441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng maxidx = symsize; 1934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1935441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1936cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t cnt; 1937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (cnt = 2; cnt < 2 + nbucket; ++cnt) 1938cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx) 1939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1940cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash bucket reference %zu out of bounds\n"), 1941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt - 2); 1942441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1943cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (; cnt < 2 + nbucket + nchain; ++cnt) 1944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx) 1945441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1946cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash chain reference %zu out of bounds\n"), 1947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt - 2 - nbucket); 1948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1950441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 1952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx, 1953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *symshdr) 1954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0]; 1956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1]; 1957441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1958441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize) 1959441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 1960441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"), 1961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), (long int) shdr->sh_size, 1962441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project (long int) ((2 + nbucket + nchain) * shdr->sh_entsize)); 1963441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1964cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t maxidx = nchain; 1965cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1966441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (symshdr != NULL) 1967441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 1968441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project size_t symsize = symshdr->sh_size / symshdr->sh_entsize; 1969441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (nchain > symshdr->sh_size / symshdr->sh_entsize) 1971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': chain array too large\n"), 1972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 1973441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng maxidx = symsize; 1975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t cnt; 1978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (cnt = 2; cnt < 2 + nbucket; ++cnt) 1979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx) 1980cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1981441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': hash bucket reference %zu out of bounds\n"), 1982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt - 2); 1983441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (; cnt < 2 + nbucket + nchain; ++cnt) 1985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx) 1986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 1987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash chain reference %" PRIu64 " out of bounds\n"), 1988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), (uint64_t) (cnt - 2 - nbucket)); 1989441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 1990441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1991441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 1992441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 1993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx, 1994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *symshdr) 1995441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 1996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0]; 1997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1]; 1998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2]; 1999441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!powerof2 (bitmask_words)) 2001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': bitmask size not power of 2: %u\n"), 2003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), bitmask_words); 2004441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t bitmask_idxmask = bitmask_words - 1; 2006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (gelf_getclass (ebl->elf) == ELFCLASS64) 2007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bitmask_words *= 2; 2008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3]; 2009441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_size < (4 + bitmask_words + nbuckets) * sizeof (Elf32_Word)) 2011441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 2012441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 2013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash table section is too small (is %ld, expected at least%ld)\n"), 2014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), (long int) shdr->sh_size, 2015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (long int) ((4 + bitmask_words + nbuckets) * sizeof (Elf32_Word))); 2016441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return; 2017441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 2018441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shift > 31) 2020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': 2nd hash function shift too big: %u\n"), 2022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), shift); 2023441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words 2025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + nbuckets); 2026441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symshdr != NULL) 2028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize); 2029441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2030cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We need the symbol section data. */ 2031cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symdata = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), NULL); 2032441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng union 2034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word *p32; 2036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Xword *p64; 2037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } bitmask = { .p32 = &((Elf32_Word *) data->d_buf)[4] }, 2038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng collected = { .p32 = xcalloc (bitmask_words, sizeof (Elf32_Word)) }; 2039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t classbits = gelf_getclass (ebl->elf) == ELFCLASS32 ? 32 : 64; 2041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t cnt; 2043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (cnt = 4 + bitmask_words; cnt < 4 + bitmask_words + nbuckets; ++cnt) 2044441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 2045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word symidx = ((Elf32_Word *) data->d_buf)[cnt]; 2046441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symidx == 0) 2048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 2049441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symidx < symbias) 2051441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 2052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"), 2054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt - (4 + bitmask_words)); 2055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 2056441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 2057441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (symidx - symbias < maxidx) 2059441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 2060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word chainhash = ((Elf32_Word *) data->d_buf)[4 2061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + bitmask_words 2062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + nbuckets 2063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + symidx 2064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng - symbias]; 2065441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symdata != NULL) 2067441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 2068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that the referenced symbol is not undefined. */ 2069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_mem; 2070cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsym (symdata, symidx, &sym_mem); 2071cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym != NULL && sym->st_shndx == SHN_UNDEF 2072cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && GELF_ST_TYPE (sym->st_info) != STT_FUNC) 2073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 2074cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"), 2075cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), symidx, 2076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt - (4 + bitmask_words)); 2077cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *symname = elf_strptr (ebl->elf, symshdr->sh_link, 2079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym->st_name); 2080cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symname != NULL) 2081cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word hval = elf_gnu_hash (symname); 2083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((hval & ~1u) != (chainhash & ~1u)) 2084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"), 2086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), symidx, 2087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt - (4 + bitmask_words)); 2088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Set the bits in the bitmask. */ 2090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t maskidx = (hval / classbits) & bitmask_idxmask; 2091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (classbits == 32) 2092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng collected.p32[maskidx] 2094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng |= UINT32_C (1) << (hval & (classbits - 1)); 2095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng collected.p32[maskidx] 2096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng |= UINT32_C (1) << ((hval >> shift) & (classbits - 1)); 2097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng collected.p64[maskidx] 2101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng |= UINT64_C (1) << (hval & (classbits - 1)); 2102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng collected.p64[maskidx] 2103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng |= UINT64_C (1) << ((hval >> shift) & (classbits - 1)); 2104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((chainhash & 1) != 0) 2109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 2110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++symidx; 2112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symidx - symbias >= maxidx) 2115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash chain for bucket %zu out of bounds\n"), 2117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt - (4 + bitmask_words)); 2118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (symshdr != NULL 2119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && symidx > symshdr->sh_size / symshdr->sh_entsize) 2120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"), 2122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt - (4 + bitmask_words)); 2123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (memcmp (collected.p32, bitmask.p32, bitmask_words * sizeof (Elf32_Word))) 2126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': bitmask does not match names in the hash table\n"), 2128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (collected.p32); 2131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 2135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_hash (int tag, Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 2136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr->e_type == ET_REL) 2138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': relocatable files cannot have hash tables\n"), 2141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 2146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 2147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 2149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr symshdr_mem; 2154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 2155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &symshdr_mem); 2156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM) 2157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash table not for dynamic symbol table\n"), 2159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_entsize != (tag == SHT_GNU_HASH 2162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? (gelf_getclass (ebl->elf) == ELFCLASS32 2163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? sizeof (Elf32_Word) : 0) 2164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng : (size_t) ebl_sysvhash_entrysize (ebl))) 2165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash table entry size incorrect\n"), 2167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((shdr->sh_flags & SHF_ALLOC) == 0) 2170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"), 2171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (shdr->sh_entsize ?: 4)) 2174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': hash table has not even room for initial administrative entries\n"), 2177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (tag) 2182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_HASH: 2184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword)) 2185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_sysv_hash64 (ebl, shdr, data, idx, symshdr); 2186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_sysv_hash (ebl, shdr, data, idx, symshdr); 2188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 2189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_GNU_HASH: 2191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_gnu_hash (ebl, shdr, data, idx, symshdr); 2192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 2193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 2195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (! "should not happen"); 2196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Compare content of both hash tables, it must be identical. */ 2201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 2202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_hash_gnu_hash (Ebl *ebl, GElf_Ehdr *ehdr, size_t hash_idx, 2203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t gnu_hash_idx) 2204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *hash_scn = elf_getscn (ebl->elf, hash_idx); 2206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *hash_data = elf_getdata (hash_scn, NULL); 2207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr hash_shdr_mem; 2208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *hash_shdr = gelf_getshdr (hash_scn, &hash_shdr_mem); 2209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *gnu_hash_scn = elf_getscn (ebl->elf, gnu_hash_idx); 2210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *gnu_hash_data = elf_getdata (gnu_hash_scn, NULL); 2211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr gnu_hash_shdr_mem; 2212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *gnu_hash_shdr = gelf_getshdr (gnu_hash_scn, &gnu_hash_shdr_mem); 2213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (hash_shdr == NULL || gnu_hash_shdr == NULL 2215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || hash_data == NULL || gnu_hash_data == NULL) 2216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* None of these pointers should be NULL since we used the 2217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sections already. We are careful nonetheless. */ 2218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The link must point to the same symbol table. */ 2221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (hash_shdr->sh_link != gnu_hash_shdr->sh_link) 2222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"), 2225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name), 2226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gnu_hash_idx, 2227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name)); 2228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *sym_scn = elf_getscn (ebl->elf, hash_shdr->sh_link); 2232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *sym_data = elf_getdata (sym_scn, NULL); 2233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr sym_shdr_mem; 2234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *sym_shdr = gelf_getshdr (sym_scn, &sym_shdr_mem); 2235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym_data == NULL || sym_shdr == NULL) 2237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int nentries = sym_shdr->sh_size / sym_shdr->sh_entsize; 2240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *used = alloca (nentries); 2241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memset (used, '\0', nentries); 2242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* First go over the GNU_HASH table and mark the entries as used. */ 2244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf; 2245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word gnu_nbucket = gnu_hasharr[0]; 2246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const int bitmap_factor = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 1 : 2; 2247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf32_Word *gnu_bucket = (gnu_hasharr 2248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + (4 + gnu_hasharr[2] * bitmap_factor)); 2249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0] - gnu_hasharr[1]; 2250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (Elf32_Word cnt = 0; cnt < gnu_nbucket; ++cnt) 2252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word symidx = gnu_bucket[cnt]; 2254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symidx != STN_UNDEF) 2255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng do 2256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng used[symidx] |= 1; 2257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((gnu_chain[symidx++] & 1u) == 0); 2258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now go over the old hash table and check that we cover the same 2261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng entries. */ 2262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (hash_shdr->sh_entsize == sizeof (Elf32_Word)) 2263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf32_Word *hasharr = (Elf32_Word *) hash_data->d_buf; 2265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word nbucket = hasharr[0]; 2266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf32_Word *bucket = &hasharr[2]; 2267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf32_Word *chain = &hasharr[2 + nbucket]; 2268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt) 2270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word symidx = bucket[cnt]; 2272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (symidx != STN_UNDEF) 2273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng used[symidx] |= 2; 2275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symidx = chain[symidx]; 2276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf64_Xword *hasharr = (Elf64_Xword *) hash_data->d_buf; 2282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Xword nbucket = hasharr[0]; 2283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf64_Xword *bucket = &hasharr[2]; 2284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf64_Xword *chain = &hasharr[2 + nbucket]; 2285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt) 2287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Xword symidx = bucket[cnt]; 2289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (symidx != STN_UNDEF) 2290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng used[symidx] |= 2; 2292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symidx = chain[symidx]; 2293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now see which entries are not set in one or both hash tables 2298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (unless the symbol is undefined in which case it can be omitted 2299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng in the new table format). */ 2300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((used[0] & 1) != 0) 2301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"), 2302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gnu_hash_idx, 2303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name)); 2304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((used[0] & 2) != 0) 2305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"), 2306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name)); 2307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int cnt = 1; cnt < nentries; ++cnt) 2309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (used[cnt] != 0 && used[cnt] != 3) 2310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (used[cnt] == 1) 2312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsymbol %d referenced in new hash table in [%2zu] '%s' but not in old hash table in [%2zu] '%s'\n"), 2314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, gnu_hash_idx, 2315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name), 2316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng hash_idx, 2317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name)); 2318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_mem; 2321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsym (sym_data, cnt, &sym_mem); 2322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym != NULL && sym->st_shndx != STN_UNDEF) 2324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsymbol %d referenced in old hash table in [%2zu] '%s' but not in new hash table in [%2zu] '%s'\n"), 2326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, hash_idx, 2327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name), 2328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gnu_hash_idx, 2329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name)); 2330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 2336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_null (Ebl *ebl, GElf_Shdr *shdr, int idx) 2337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define TEST(name, extra) \ 2339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (extra && shdr->sh_##name != 0) \ 2340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': nonzero sh_%s for NULL section\n"), \ 2341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), #name) 2342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TEST (name, 1); 2344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TEST (flags, 1); 2345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TEST (addr, 1); 2346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TEST (offset, 1); 2347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TEST (size, idx != 0); 2348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TEST (link, idx != 0); 2349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TEST (info, 1); 2350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TEST (addralign, 1); 2351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng TEST (entsize, 1); 2352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 2356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 2357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr->e_type != ET_REL) 2359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': section groups only allowed in relocatable object files\n"), 2362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that sh_link is an index of a symbol table. */ 2367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 2368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr symshdr_mem; 2369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 2370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symshdr == NULL) 2371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get symbol table: %s\n"), 2372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), elf_errmsg (-1)); 2373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symshdr->sh_type != SHT_SYMTAB) 2376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': section reference in sh_link is no symbol table\n"), 2378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM, 2381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1, EV_CURRENT)) 2382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': invalid symbol index in sh_info\n"), 2384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_flags != 0) 2387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': sh_flags not zero\n"), 2388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_data; 2391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsym (elf_getdata (symscn, NULL), shdr->sh_info, 2392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &sym_data); 2393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym == NULL) 2394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': cannot get symbol for signature\n"), 2396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (strcmp (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name), 2398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng "") == 0) 2399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': signature symbol canot be empty string\n"), 2401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (be_strict 2404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT)) 2405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': sh_flags not set correctly\n"), 2406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 2410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 2411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"), 2412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), elf_errmsg (-1)); 2413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT); 2416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t cnt; 2417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Word val; 2418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data->d_size % elsize != 0) 2420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"), 2422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data->d_size < elsize) 2425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': section group without flags word\n"), 2427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (be_strict) 2429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data->d_size < 2 * elsize) 2431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': section group without member\n"), 2433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (data->d_size < 3 * elsize) 2435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': section group with only one member\n"), 2437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#if ALLOW_UNALIGNED 2441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng val = *((Elf32_Word *) data->d_buf); 2442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 2443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&val, data->d_buf, elsize); 2444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 2445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((val & ~GRP_COMDAT) != 0) 2446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': unknown section group flags\n"), 2447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (cnt = elsize; cnt < data->d_size; cnt += elsize) 2450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#if ALLOW_UNALIGNED 2452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng val = *((Elf32_Word *) ((char *) data->d_buf + cnt)); 2453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 2454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&val, (char *) data->d_buf + cnt, elsize); 2455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 2456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (val > shnum) 2458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': section index %Zu out of range\n"), 2460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt / elsize); 2461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr refshdr_mem; 2464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *refshdr = gelf_getshdr (elf_getscn (ebl->elf, val), 2465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &refshdr_mem); 2466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (refshdr == NULL) 2467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': cannot get section header for element %zu: %s\n"), 2469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt / elsize, 2470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_errmsg (-1)); 2471441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 2472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 2473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (refshdr->sh_type == SHT_GROUP) 2474441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 2475441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': section group contains another group [%2d] '%s'\n"), 2476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 2477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng val, section_name (ebl, val)); 2478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((refshdr->sh_flags & SHF_GROUP) == 0) 2480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 2481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s': element %Zu references section [%2d] '%s' without SHF_GROUP flag set\n"), 2482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt / elsize, 2483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng val, section_name (ebl, val)); 2484441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 2485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 2486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (++scnref[val] == 2) 2487441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 2488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s' is contained in more than one section group\n"), 2489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng val, section_name (ebl, val)); 2490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 2491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 2492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 2493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char * 2497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection_flags_string (GElf_Word flags, char *buf, size_t len) 2498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (flags == 0) 2500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return "none"; 2501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng static const struct 2503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word flag; 2505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name; 2506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } known_flags[] = 2507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define NEWFLAG(name) { SHF_##name, #name } 2509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NEWFLAG (WRITE), 2510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NEWFLAG (ALLOC), 2511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NEWFLAG (EXECINSTR), 2512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NEWFLAG (MERGE), 2513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NEWFLAG (STRINGS), 2514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NEWFLAG (INFO_LINK), 2515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NEWFLAG (LINK_ORDER), 2516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NEWFLAG (OS_NONCONFORMING), 2517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NEWFLAG (GROUP), 2518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng NEWFLAG (TLS) 2519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 2520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#undef NEWFLAG 2521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]); 2522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *cp = buf; 2524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t cnt = 0; cnt < nknown_flags; ++cnt) 2526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (flags & known_flags[cnt].flag) 2527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (cp != buf && len > 1) 2529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = '|'; 2531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng --len; 2532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name)); 2535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cp = mempcpy (cp, known_flags[cnt].name, ncopy); 2536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng len -= ncopy; 2537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng flags ^= known_flags[cnt].flag; 2539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (flags != 0 || cp == buf) 2542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags); 2543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp = '\0'; 2545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return buf; 2547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 2551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghas_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx) 2552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* First find the relocation section for the symbol table. */ 2554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = NULL; 2555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 2556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = NULL; 2557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 2558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr = gelf_getshdr (scn, &shdr_mem); 2560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr != NULL 2561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) 2562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && shdr->sh_link == symscnndx) 2563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Found the section. */ 2564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 2565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (scn == NULL) 2568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 2569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (scn, NULL); 2571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 2572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 2573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_type == SHT_REL) 2575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i) 2576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel rel_mem; 2578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel *rel = gelf_getrel (data, i, &rel_mem); 2579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (rel == NULL) 2580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 2581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (GELF_R_SYM (rel->r_info) == symndx 2583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info))) 2584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 1; 2585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i) 2588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela rela_mem; 2590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela *rela = gelf_getrela (data, i, &rela_mem); 2591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (rela == NULL) 2592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 2593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (GELF_R_SYM (rela->r_info) == symndx 2595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info))) 2596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 1; 2597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 2600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 2604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengin_nobits_scn (Ebl *ebl, unsigned int shndx) 2605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 2607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, shndx), &shdr_mem); 2608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return shdr != NULL && shdr->sh_type == SHT_NOBITS; 2609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic struct version_namelist 2613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *objname; 2615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name; 2616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Versym ndx; 2617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng enum { ver_def, ver_need } type; 2618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct version_namelist *next; 2619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} *version_namelist; 2620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 2623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengadd_version (const char *objname, const char *name, GElf_Versym ndx, int type) 2624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that there are no duplications. */ 2626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct version_namelist *nlp = version_namelist; 2627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (nlp != NULL) 2628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (((nlp->objname == NULL && objname == NULL) 2630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (nlp->objname != NULL && objname != NULL 2631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && strcmp (nlp->objname, objname) == 0)) 2632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && strcmp (nlp->name, name) == 0) 2633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return nlp->type == ver_def ? 1 : -1; 2634cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nlp = nlp->next; 2635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nlp = xmalloc (sizeof (*nlp)); 2638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nlp->objname = objname; 2639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nlp->name = name; 2640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nlp->ndx = ndx; 2641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nlp->type = type; 2642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nlp->next = version_namelist; 2643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng version_namelist = nlp; 2644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 2646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 2650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_versym (Ebl *ebl, int idx) 2651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = elf_getscn (ebl->elf, idx); 2653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 2654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 2655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr == NULL) 2656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The error has already been reported. */ 2657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (scn, NULL); 2660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 2661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 2663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link); 2668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr symshdr_mem; 2669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); 2670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symshdr == NULL) 2671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The error has already been reported. */ 2672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symshdr->sh_type != SHT_DYNSYM) 2675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"), 2678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 2679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_link, section_name (ebl, shdr->sh_link)); 2680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The number of elements in the version symbol table must be the 2684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng same as the number of symbols. */ 2685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_size / shdr->sh_entsize 2686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng != symshdr->sh_size / symshdr->sh_entsize) 2687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"), 2689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), 2690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr->sh_link, section_name (ebl, shdr->sh_link)); 2691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *symdata = elf_getdata (symscn, NULL); 2693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (symdata == NULL) 2694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The error has already been reported. */ 2695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int cnt = 1; (size_t) cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) 2698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Versym versym_mem; 2700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Versym *versym = gelf_getversym (data, cnt, &versym_mem); 2701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (versym == NULL) 2702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': symbol %d: cannot read version data\n"), 2705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 2706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 2707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym_mem; 2710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_mem); 2711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym == NULL) 2712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Already reported elsewhere. */ 2713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 2714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*versym == VER_NDX_GLOBAL) 2716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Global symbol. Make sure it is not defined as local. */ 2718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (GELF_ST_BIND (sym->st_info) == STB_LOCAL) 2719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': symbol %d: local symbol with global scope\n"), 2721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 2722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (*versym != VER_NDX_LOCAL) 2724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Versioned symbol. Make sure it is not defined as local. */ 2726cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!gnuld && GELF_ST_BIND (sym->st_info) == STB_LOCAL) 2727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2728cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': symbol %d: local symbol with version\n"), 2729cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 2730cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2731cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Look through the list of defined versions and locate the 2732cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng index we need for this symbol. */ 2733cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct version_namelist *runp = version_namelist; 2734cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (runp != NULL) 2735cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (runp->ndx == (*versym & (GElf_Versym) 0x7fff)) 2736cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 2737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2738cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng runp = runp->next; 2739cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (runp == NULL) 2741cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2742cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': symbol %d: invalid version index %d\n"), 2743cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, (int) *versym); 2744cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (sym->st_shndx == SHN_UNDEF 2745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && runp->type == ver_def) 2746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': symbol %d: version index %d is for defined version\n"), 2748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, (int) *versym); 2749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (sym->st_shndx != SHN_UNDEF 2750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && runp->type == ver_need) 2751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2752cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Unless this symbol has a copy relocation associated 2753cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng this must not happen. */ 2754cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!has_copy_reloc (ebl, shdr->sh_link, cnt) 2755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !in_nobits_scn (ebl, sym->st_shndx)) 2756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': symbol %d: version index %d is for requested version\n"), 2758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, (int) *versym); 2759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2760cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2761cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2762cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 2766cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengunknown_dependency_p (Elf *elf, GElf_Ehdr *ehdr, const char *fname) 2767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr_mem; 2769cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr = NULL; 2770cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2771cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int i; 2772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (i = 0; i < ehdr->e_phnum; ++i) 2773cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL 2774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && phdr->p_type == PT_DYNAMIC) 2775cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 2776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2777cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (i == ehdr->e_phnum) 2778cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 1; 2779cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (phdr != NULL); 2780cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset); 2781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 2782cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 2783cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (scn, NULL); 2784cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL) 2785cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j) 2786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Dyn dyn_mem; 2788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem); 2789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dyn != NULL && dyn->d_tag == DT_NEEDED) 2790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *str = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val); 2792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (str != NULL && strcmp (str, fname) == 0) 2793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Found it. */ 2794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 2795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 1; 2799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic unsigned int nverneed; 2803cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 2805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_verneed (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 2806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (++nverneed == 2) 2808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("more than one version reference section present\n")); 2809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr strshdr_mem; 2811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 2812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &strshdr_mem); 2813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strshdr == NULL) 2814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2815cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strshdr->sh_type != SHT_STRTAB) 2816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': sh_link does not link to string table\n"), 2818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 2821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 2822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 2824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int offset = 0; 2828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int cnt = shdr->sh_info; --cnt >= 0; ) 2829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Get the data at the next offset. */ 2831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Verneed needmem; 2832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Verneed *need = gelf_getverneed (data, offset, &needmem); 2833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (need == NULL) 2834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 2835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int auxoffset = offset + need->vn_aux; 2837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (need->vn_version != EV_CURRENT) 2839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has wrong version %d\n"), 2841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, (int) need->vn_version); 2842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED, 2844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1, EV_CURRENT)) 2845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"), 2847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 2848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *libname = elf_strptr (ebl->elf, shdr->sh_link, 2850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng need->vn_file); 2851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (libname == NULL) 2852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has invalid file reference\n"), 2855cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 2856cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto next_need; 2857cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that there is a DT_NEEDED entry for the referenced library. */ 2860cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unknown_dependency_p (ebl->elf, ehdr, libname)) 2861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d references unknown dependency\n"), 2863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 2864cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int cnt2 = need->vn_cnt; --cnt2 >= 0; ) 2866cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Vernaux auxmem; 2868cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem); 2869cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (aux == NULL) 2870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 2871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((aux->vna_flags & ~VER_FLG_WEAK) != 0) 2873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2874cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"), 2875cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt); 2876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2877cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *verstr = elf_strptr (ebl->elf, shdr->sh_link, 2878cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng aux->vna_name); 2879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (verstr == NULL) 2880cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2881cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"), 2882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt); 2883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 2884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word hashval = elf_hash (verstr); 2886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (hashval != aux->vna_hash) 2887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, expected %#x\n"), 2889cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), need->vn_cnt - cnt2, 2890cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, (int) hashval, (int) aux->vna_hash); 2891cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2892cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int res = add_version (libname, verstr, aux->vna_other, 2893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ver_need); 2894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (res !=0)) 2895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (res > 0); 2897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"), 2899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), need->vn_cnt - cnt2, 2900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, verstr); 2901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((aux->vna_next != 0 || cnt2 > 0) 2905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && aux->vna_next < gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, 2906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng EV_CURRENT)) 2907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2908cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2909cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"), 2910cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt); 2911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 2912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng auxoffset += MAX (aux->vna_next, 2915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, EV_CURRENT)); 2916cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Find the next offset. */ 2919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng next_need: 2920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng offset += need->vn_next; 2921cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((need->vn_next != 0 || cnt > 0) 2923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && offset < auxoffset) 2924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has invalid offset to next entry\n"), 2926cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 2927cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2928cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 2929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic unsigned int nverdef; 2932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 2934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_verdef (Ebl *ebl, GElf_Shdr *shdr, int idx) 2935cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 2936cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (++nverdef == 2) 2937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("more than one version definition section present\n")); 2938cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr strshdr_mem; 2940cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), 2941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &strshdr_mem); 2942cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strshdr == NULL) 2943cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strshdr->sh_type != SHT_STRTAB) 2945cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2946cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': sh_link does not link to string table\n"), 2947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 2950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 2951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng no_data: 2953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 2954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 2956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Iterate over all version definition entries. We check that there 2959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng is a BASE entry and that each index is unique. To do the later 2960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng we collection the information in a list which is later 2961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng examined. */ 2962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct namelist 2963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2964cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name; 2965cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct namelist *next; 2966cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } *namelist = NULL; 2967cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct namelist *refnamelist = NULL; 2968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool has_base = false; 2970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int offset = 0; 2971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int cnt = shdr->sh_info; --cnt >= 0; ) 2972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Get the data at the next offset. */ 2974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Verdef defmem; 2975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Verdef *def = gelf_getverdef (data, offset, &defmem); 2976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (def == NULL) 2977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto no_data; 2978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((def->vd_flags & VER_FLG_BASE) != 0) 2980cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 2981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (has_base) 2982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': more than one BASE definition\n"), 2984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (def->vd_ndx != VER_NDX_GLOBAL) 2986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"), 2988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 2989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng has_base = true; 2990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 2991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((def->vd_flags & ~(VER_FLG_BASE|VER_FLG_WEAK)) != 0) 2992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has unknown flag\n"), 2994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 2995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (def->vd_version != EV_CURRENT) 2997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 2998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has wrong version %d\n"), 2999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, (int) def->vd_version); 3000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF, 3002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1, EV_CURRENT)) 3003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has wrong offset of auxiliary data\n"), 3005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 3006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int auxoffset = offset + def->vd_aux; 3008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Verdaux auxmem; 3009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem); 3010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (aux == NULL) 3011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto no_data; 3012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name); 3014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (name == NULL) 3015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has invalid name reference\n"), 3018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 3019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto next_def; 3020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word hashval = elf_hash (name); 3022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (def->vd_hash != hashval) 3023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"), 3025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, (int) hashval, 3026cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) def->vd_hash); 3027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int res = add_version (NULL, name, def->vd_ndx, ver_def); 3029cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (res !=0)) 3030cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3031cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (res > 0); 3032cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has duplicate version name '%s'\n"), 3034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt, name); 3035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct namelist *newname = alloca (sizeof (*newname)); 3038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newname->name = name; 3039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newname->next = namelist; 3040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng namelist = newname; 3041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng auxoffset += aux->vda_next; 3043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2) 3044cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng aux = gelf_getverdaux (data, auxoffset, &auxmem); 3046cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (aux == NULL) 3047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto no_data; 3048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3049cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name); 3050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (name == NULL) 3051cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"), 3053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 3054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 3055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newname = alloca (sizeof (*newname)); 3057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newname->name = name; 3058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newname->next = refnamelist; 3059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng refnamelist = newname; 3060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((aux->vda_next != 0 || cnt2 + 1 < def->vd_cnt) 3063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && aux->vda_next < gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, 3064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng EV_CURRENT)) 3065cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has wrong next field in auxiliary data\n"), 3068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 3069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3070cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3071cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3072cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng auxoffset += MAX (aux->vda_next, 3073cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, EV_CURRENT)); 3074cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3075cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Find the next offset. */ 3077cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng next_def: 3078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng offset += def->vd_next; 3079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3080cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((def->vd_next != 0 || cnt > 0) 3081cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && offset < auxoffset) 3082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': entry %d has invalid offset to next entry\n"), 3084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), cnt); 3085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!has_base) 3088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': no BASE definition\n"), 3089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 3090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check whether the referenced names are available. */ 3092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (namelist != NULL) 3093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct version_namelist *runp = version_namelist; 3095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (runp != NULL) 3096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (runp->type == ver_def 3098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && strcmp (runp->name, namelist->name) == 0) 3099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng runp = runp->next; 3101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (runp == NULL) 3104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': unknown parent version '%s'\n"), 3106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), namelist->name); 3107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng namelist = namelist->next; 3109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 3111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 3113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 3114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 3115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_size == 0) 3116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': empty object attributes section\n"), 3118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 3119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 3120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL); 3123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL || data->d_size == 0) 3124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 3126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 3127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 3128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline size_t pos (const unsigned char *p) 3131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return p - (const unsigned char *) data->d_buf; 3133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const unsigned char *p = data->d_buf; 3136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*p++ != 'A') 3137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': unrecognized attribute format\n"), 3139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 3140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 3141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline size_t left (void) 3144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (const unsigned char *) data->d_buf + data->d_size - p; 3146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (left () >= 4) 3149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint32_t len; 3151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&len, p, sizeof len); 3152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (len == 0) 3154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: zero length field in attribute section\n"), 3156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (p)); 3157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (MY_ELFDATA != ehdr->e_ident[EI_DATA]) 3159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CONVERT (len); 3160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (len > left ()) 3162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: invalid length in attribute section\n"), 3165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (p)); 3166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const unsigned char *name = p + sizeof len; 3170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng p += len; 3171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned const char *q = memchr (name, '\0', len); 3173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (q == NULL) 3174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: unterminated vendor name string\n"), 3177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (p)); 3178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 3179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++q; 3181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (q - name == sizeof "gnu" && !memcmp (name, "gnu", sizeof "gnu")) 3183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (q < p) 3184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned const char *chunk = q; 3186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int subsection_tag; 3188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng get_uleb128 (subsection_tag, q); 3189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (q >= p) 3191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"), 3194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (chunk)); 3195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint32_t subsection_len; 3199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (p - q < (ptrdiff_t) sizeof subsection_len) 3200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: truncated attribute section\n"), 3203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (q)); 3204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&subsection_len, q, sizeof subsection_len); 3208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (subsection_len == 0) 3209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: zero length field in attribute subsection\n"), 3212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (q)); 3213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng q += sizeof subsection_len; 3215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 3216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (MY_ELFDATA != ehdr->e_ident[EI_DATA]) 3219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CONVERT (subsection_len); 3220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (p - chunk < (ptrdiff_t) subsection_len) 3222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: invalid length in attribute subsection\n"), 3225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (q)); 3226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const unsigned char *subsection_end = chunk + subsection_len; 3230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng chunk = q; 3231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng q = subsection_end; 3232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (subsection_tag != 1) /* Tag_File */ 3234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"), 3236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (chunk), subsection_tag); 3237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 3238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng chunk += sizeof subsection_len; 3240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (chunk < q) 3241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int tag; 3243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng get_uleb128 (tag, chunk); 3244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint64_t value = 0; 3246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const unsigned char *r = chunk; 3247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (tag == 32 || (tag & 1) == 0) 3248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng get_uleb128 (value, r); 3250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r > q) 3251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"), 3254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (chunk)); 3255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (tag == 32 || (tag & 1) != 0) 3259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng r = memchr (r, '\0', q - r); 3261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r == NULL) 3262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: unterminated string in attribute\n"), 3265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (chunk)); 3266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++r; 3269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *tag_name = NULL; 3272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *value_name = NULL; 3273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!ebl_check_object_attribute (ebl, (const char *) name, 3274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng tag, value, 3275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &tag_name, &value_name)) 3276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"), 3278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (chunk), tag); 3279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if ((tag & 1) == 0 && value_name == NULL) 3280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"), 3282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (chunk), 3283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng tag_name, value); 3284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng chunk = r; 3286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 3290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: vendor '%s' unknown\n"), 3292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (p), name); 3293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3294441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (left () != 0) 3296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': offset %zu: extra bytes after last attribute section\n"), 3298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), pos (p)); 3299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 3300441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3301441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool has_loadable_segment; 3302441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic bool has_interp_segment; 3303441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3304441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic const struct 3305441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 3306441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project const char *name; 3307441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project size_t namelen; 3308441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Word type; 3309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng enum { unused, exact, atleast, exact_or_gnuld } attrflag; 3310441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Word attr; 3311441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Word attr2; 3312441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} special_sections[] = 3313441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3314441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* See figure 4-14 in the gABI. */ 3315441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 }, 3316441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".comment", 8, SHT_PROGBITS, exact, 0, 0 }, 3317441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 }, 3318441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 }, 3319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { ".debug_str", 11, SHT_PROGBITS, exact_or_gnuld, SHF_MERGE | SHF_STRINGS, 0 }, 3320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { ".debug", 6, SHT_PROGBITS, exact, 0, 0 }, 3321441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE }, 3322441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 }, 3323441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 }, 3324441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 }, 3325441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 }, 3326441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info? 3327441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 }, 3328441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 }, 3329441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 }, 3330441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests? 3331441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".line", 6, SHT_PROGBITS, exact, 0, 0 }, 3332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { ".note", 6, SHT_NOTE, atleast, 0, SHF_ALLOC }, 3333441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests 3334441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 }, 3335441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC }, // XXX more tests 3336441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC }, // XXX more tests 3337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS }, 3338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS }, 3339441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 }, 3340441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests 3341441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests 3342441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests 3343441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 }, 3344441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 }, 3345441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 }, 3346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 }, 3347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The following are GNU extensions. */ 3349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 }, 3350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 }, 3351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 }, 3352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { ".gnu.attributes", 16, SHT_GNU_ATTRIBUTES, exact, 0, 0 }, 3353441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project }; 3354441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define nspecial_sections \ 3355441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project (sizeof (special_sections) / sizeof (special_sections[0])) 3356441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define IS_KNOWN_SPECIAL(idx, string, prefix) \ 3358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (special_sections[idx].namelen == sizeof string - (prefix ? 1 : 0) \ 3359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !memcmp (special_sections[idx].name, string, \ 3360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sizeof string - (prefix ? 1 : 0))) 3361441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3362441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 3363441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_sections (Ebl *ebl, GElf_Ehdr *ehdr) 3364441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 3365441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_shoff == 0) 3366441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* No section header. */ 3367441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return; 3368441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3369441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Allocate array to count references in section groups. */ 3370441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project scnref = (int *) xcalloc (shnum, sizeof (int)); 3371441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3372441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check the zeroth section first. It must not have any contents 3373441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project and the section header must contain nonzero value at most in the 3374441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project sh_size and sh_link fields. */ 3375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 3376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem); 3377441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr == NULL) 3378441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("cannot get section header of zeroth section\n")); 3379441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 3380441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3381441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_name != 0) 3382441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("zeroth section has nonzero name\n")); 3383441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_type != 0) 3384441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("zeroth section has nonzero type\n")); 3385441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_flags != 0) 3386441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("zeroth section has nonzero flags\n")); 3387441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_addr != 0) 3388441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("zeroth section has nonzero address\n")); 3389441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_offset != 0) 3390441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("zeroth section has nonzero offset\n")); 3391441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_info != 0) 3392441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("zeroth section has nonzero info field\n")); 3393441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_addralign != 0) 3394441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("zeroth section has nonzero align value\n")); 3395441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_entsize != 0) 3396441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("zeroth section has nonzero entry size value\n")); 3397441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3398441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_size != 0 && ehdr->e_shnum != 0) 3399441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3400441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectzeroth section has nonzero size value while ELF header has nonzero shnum value\n")); 3401441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3402441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX) 3403441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3404441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectzeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n")); 3405441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3406441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int *segment_flags = xcalloc (ehdr->e_phnum, sizeof segment_flags[0]); 3408441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool dot_interp_section = false; 3410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t hash_idx = 0; 3412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t gnu_hash_idx = 0; 3413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t versym_scnndx = 0; 3415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t cnt = 1; cnt < shnum; ++cnt) 3416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &shdr_mem); 3418441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr == NULL) 3419441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3420441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3421441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcannot get section header for section [%2zu] '%s': %s\n"), 3422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt), elf_errmsg (-1)); 3423441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 3424441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3425441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3426441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name); 3427441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3428441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (scnname == NULL) 3429441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("section [%2zu]: invalid name\n"), cnt); 3430441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 3431441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3432441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check whether it is one of the special sections defined in 3433441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project the gABI. */ 3434441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project size_t s; 3435441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (s = 0; s < nspecial_sections; ++s) 3436441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (strncmp (scnname, special_sections[s].name, 3437441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project special_sections[s].namelen) == 0) 3438441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3439441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char stbuf1[100]; 3440441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char stbuf2[100]; 3441441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project char stbuf3[100]; 3442441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Word good_type = special_sections[s].type; 3444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (IS_KNOWN_SPECIAL (s, ".plt", false) 3445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ebl_bss_plt_p (ebl, ehdr)) 3446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng good_type = SHT_NOBITS; 3447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* In a debuginfo file, any normal section can be SHT_NOBITS. 3449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This is only invalid for DWARF sections and .shstrtab. */ 3450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_type != good_type 3451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (shdr->sh_type != SHT_NOBITS 3452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || !is_debuginfo 3453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || IS_KNOWN_SPECIAL (s, ".debug_str", false) 3454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || IS_KNOWN_SPECIAL (s, ".debug", true) 3455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || IS_KNOWN_SPECIAL (s, ".shstrtab", false))) 3456441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3457441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2d] '%s' has wrong type: expected %s, is %s\n"), 3458441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project (int) cnt, scnname, 3459441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl_section_type_name (ebl, special_sections[s].type, 3460441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project stbuf1, sizeof (stbuf1)), 3461441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl_section_type_name (ebl, shdr->sh_type, 3462441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project stbuf2, sizeof (stbuf2))); 3463441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (special_sections[s].attrflag == exact 3465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || special_sections[s].attrflag == exact_or_gnuld) 3466441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3467441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Except for the link order and group bit all the 3468441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project other bits should match exactly. */ 3469441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP)) 3470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng != special_sections[s].attr 3471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (special_sections[s].attrflag == exact || !gnuld)) 3472441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3473441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has wrong flags: expected %s, is %s\n"), 3474441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cnt, scnname, 3475441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project section_flags_string (special_sections[s].attr, 3476441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project stbuf1, sizeof (stbuf1)), 3477441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project section_flags_string (shdr->sh_flags 3478441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project & ~SHF_LINK_ORDER, 3479441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project stbuf2, sizeof (stbuf2))); 3480441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3481441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (special_sections[s].attrflag == atleast) 3482441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3483441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((shdr->sh_flags & special_sections[s].attr) 3484441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project != special_sections[s].attr 3485441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project || ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP 3486441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project | special_sections[s].attr 3487441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project | special_sections[s].attr2)) 3488441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project != 0)) 3489441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3490441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"), 3491441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cnt, scnname, 3492441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project section_flags_string (special_sections[s].attr, 3493441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project stbuf1, sizeof (stbuf1)), 3494441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project section_flags_string (special_sections[s].attr2, 3495441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project stbuf2, sizeof (stbuf2)), 3496441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project section_flags_string (shdr->sh_flags 3497441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project & ~(SHF_LINK_ORDER 3498441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project | SHF_GROUP), 3499441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project stbuf3, sizeof (stbuf3))); 3500441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3501441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3502441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (strcmp (scnname, ".interp") == 0) 3503441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3504441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project dot_interp_section = true; 3505441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3506441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_type == ET_REL) 3507441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3508441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' present in object file\n"), 3509441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cnt, scnname); 3510441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3511441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((shdr->sh_flags & SHF_ALLOC) != 0 3512441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && !has_loadable_segment) 3513441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3514441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"), 3515441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cnt, scnname); 3516441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if ((shdr->sh_flags & SHF_ALLOC) == 0 3517441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && has_loadable_segment) 3518441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3519441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"), 3520441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cnt, scnname); 3521441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3522441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 3523441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3524441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (strcmp (scnname, ".symtab_shndx") == 0 3525441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && ehdr->e_type != ET_REL) 3526441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3527441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' is extension section index table in non-object file\n"), 3528441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cnt, scnname); 3529441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3530441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* These sections must have the SHF_ALLOC flag set iff 3531441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project a loadable segment is available. 3532441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3533441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project .relxxx 3534441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project .strtab 3535441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project .symtab 3536441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project .symtab_shndx 3537441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3538441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Check that if there is a reference from the 3539441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project loaded section these sections also have the 3540441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ALLOC flag set. */ 3541441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#if 0 3542441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project // XXX TODO 3543441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((shdr->sh_flags & SHF_ALLOC) != 0 3544441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && !has_loadable_segment) 3545441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3546441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"), 3547441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cnt, scnname); 3548441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if ((shdr->sh_flags & SHF_ALLOC) == 0 3549441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && has_loadable_segment) 3550441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3551441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"), 3552441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cnt, scnname); 3553441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#endif 3554441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3555441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3556441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3557441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3558441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3559441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3560441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize) 3561441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3562441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': size not multiple of entry size\n"), 3563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 3564441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3565441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL) 3566441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("cannot get section header\n")); 3567441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3568441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_type >= SHT_NUM 3569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && shdr->sh_type != SHT_GNU_ATTRIBUTES 3570441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && shdr->sh_type != SHT_GNU_LIBLIST 3571441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && shdr->sh_type != SHT_CHECKSUM 3572441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && shdr->sh_type != SHT_GNU_verdef 3573441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && shdr->sh_type != SHT_GNU_verneed 3574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && shdr->sh_type != SHT_GNU_versym 3575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ebl_section_type_name (ebl, shdr->sh_type, NULL, 0) == NULL) 3576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2zu] '%s' has unsupported type %d\n"), 3577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt), 3578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) shdr->sh_type); 3579441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3580441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \ 3581441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \ 3582441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS) 3583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS) 3584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS; 3586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sh_flags & SHF_MASKPROC) 3587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!ebl_machine_section_flag_check (ebl, 3589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sh_flags & SHF_MASKPROC)) 3590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2zu] '%s'" 3591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng " contains invalid processor-specific flag(s)" 3592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng " %#" PRIx64 "\n"), 3593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC); 3594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sh_flags &= ~(GElf_Xword) SHF_MASKPROC; 3595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sh_flags != 0) 3597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2zu] '%s' contains unknown flag(s)" 3598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng " %#" PRIx64 "\n"), 3599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt), sh_flags); 3600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_flags & SHF_TLS) 3602441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3603441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project // XXX Correct? 3604441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_addr != 0 && !gnuld) 3605441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3606441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': thread-local data sections address not zero\n"), 3607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 3608441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3609441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project // XXX TODO more tests!? 3610441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3611441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3612441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_link >= shnum) 3613441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3614441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': invalid section reference in link value\n"), 3615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 3616441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3617441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum) 3618441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3619441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': invalid section reference in info value\n"), 3620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 3621441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3622441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((shdr->sh_flags & SHF_MERGE) == 0 3623441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && (shdr->sh_flags & SHF_STRINGS) != 0 3624441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && be_strict) 3625441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3626441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': strings flag set without merge flag\n"), 3627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 3628441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3629441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0) 3630441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3631441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': merge flag set but entry size is zero\n"), 3632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 3633441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3634441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_flags & SHF_GROUP) 3635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_scn_group (ebl, cnt); 3636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_flags & SHF_EXECINSTR) 3638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (shdr->sh_type) 3640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_PROGBITS: 3642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_NOBITS: 3645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (is_debuginfo) 3646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 3648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2zu] '%s' has unexpected type %d for an executable section\n"), 3650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt), shdr->sh_type); 3651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((shdr->sh_flags & SHF_WRITE) 3655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !ebl_check_special_section (ebl, cnt, shdr, 3656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng section_name (ebl, cnt))) 3657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2zu] '%s' is both executable and writable\n"), 3659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 3660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3661441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3662441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0) 3663441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3664441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Make sure the section is contained in a loaded segment 3665441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project and that the initialization part matches NOBITS sections. */ 3666441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int pcnt; 3667441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Phdr phdr_mem; 3668441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Phdr *phdr; 3669441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3670441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt) 3671441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL 3672441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && ((phdr->p_type == PT_LOAD 3673441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && (shdr->sh_flags & SHF_TLS) == 0) 3674441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project || (phdr->p_type == PT_TLS 3675441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && (shdr->sh_flags & SHF_TLS) != 0)) 3676441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && phdr->p_offset <= shdr->sh_offset 3677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (phdr->p_offset + phdr->p_filesz > shdr->sh_offset 3678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (phdr->p_offset + phdr->p_memsz > shdr->sh_offset 3679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && shdr->sh_type == SHT_NOBITS))) 3680441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3681441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Found the segment. */ 3682441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (phdr->p_offset + phdr->p_memsz 3683441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project < shdr->sh_offset + shdr->sh_size) 3684441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3685441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' not fully contained in segment of program header entry %d\n"), 3686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt), pcnt); 3687441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3688441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (shdr->sh_type == SHT_NOBITS) 3689441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz 3691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !is_debuginfo) 3692441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3693441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"), 3694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt), pcnt); 3695441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3696441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 3697441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const GElf_Off end = phdr->p_offset + phdr->p_filesz; 3699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_offset > end || 3700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (shdr->sh_offset == end && shdr->sh_size != 0)) 3701441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3702441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"), 3703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt), pcnt); 3704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_type != SHT_NOBITS) 3707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((shdr->sh_flags & SHF_EXECINSTR) != 0) 3709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng segment_flags[pcnt] |= PF_X; 3711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((phdr->p_flags & PF_X) == 0) 3712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2zu] '%s' is executable in nonexecutable segment %d\n"), 3714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt), pcnt); 3715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((shdr->sh_flags & SHF_WRITE) != 0) 3718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng segment_flags[pcnt] |= PF_W; 3720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (0 /* XXX vdso images have this */ 3721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (phdr->p_flags & PF_W) == 0) 3722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2zu] '%s' is writable in unwritable segment %d\n"), 3724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt), pcnt); 3725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3726441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3727441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3728441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3729441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3730441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3731441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (pcnt == ehdr->e_phnum) 3732441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3733441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': alloc flag set but section not in any loaded segment\n"), 3734cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 3735441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3736441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3737441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB) 3738441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3739441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectsection [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"), 3740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 3741441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3742441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project switch (shdr->sh_type) 3743441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3744441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case SHT_DYNSYM: 3745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr->e_type == ET_REL) 3746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"), 3748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, section_name (ebl, cnt)); 3749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* FALLTHROUGH */ 3750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_SYMTAB: 3751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_symtab (ebl, ehdr, shdr, cnt); 3752441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3753441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3754441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case SHT_RELA: 3755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_rela (ebl, ehdr, shdr, cnt); 3756441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3757441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3758441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case SHT_REL: 3759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_rel (ebl, ehdr, shdr, cnt); 3760441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3761441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3762441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case SHT_DYNAMIC: 3763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_dynamic (ebl, ehdr, shdr, cnt); 3764441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3765441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3766441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case SHT_SYMTAB_SHNDX: 3767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_symtab_shndx (ebl, ehdr, shdr, cnt); 3768441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3769441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3770441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case SHT_HASH: 3771cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt); 3772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng hash_idx = cnt; 3773cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3775cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_GNU_HASH: 3776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt); 3777cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gnu_hash_idx = cnt; 3778441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3779441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3780441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case SHT_NULL: 3781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_null (ebl, shdr, cnt); 3782441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3783441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3784441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case SHT_GROUP: 3785441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project check_group (ebl, ehdr, shdr, cnt); 3786441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3787441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_NOTE: 3789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_note_section (ebl, ehdr, shdr, cnt); 3790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3792441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project case SHT_GNU_versym: 3793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We cannot process this section now since we have no guarantee 3794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng that the verneed and verdef sections have already been read. 3795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Just remember the section index. */ 3796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (versym_scnndx != 0) 3797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("more than one version symbol table present\n")); 3798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng versym_scnndx = cnt; 3799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_GNU_verneed: 3802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_verneed (ebl, ehdr, shdr, cnt); 3803cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_GNU_verdef: 3806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_verdef (ebl, shdr, cnt); 3807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_GNU_ATTRIBUTES: 3810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_attributes (ebl, ehdr, shdr, cnt); 3811441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3812441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3813441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project default: 3814441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Nothing. */ 3815441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3816441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3817441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3818441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3819441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (has_interp_segment && !dot_interp_section) 3820441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("INTERP program header entry but no .interp section\n")); 3821441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!is_debuginfo) 3823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt) 3824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr_mem; 3826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem); 3827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr != NULL && (phdr->p_type == PT_LOAD || phdr->p_type == PT_TLS)) 3828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((phdr->p_flags & PF_X) != 0 3830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (segment_flags[pcnt] & PF_X) == 0) 3831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengloadable segment [%u] is executable but contains no executable sections\n"), 3833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng pcnt); 3834441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((phdr->p_flags & PF_W) != 0 3836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (segment_flags[pcnt] & PF_W) == 0) 3837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengloadable segment [%u] is writable but contains no writable sections\n"), 3839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng pcnt); 3840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3842441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (segment_flags); 3844441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (version_namelist != NULL) 3846441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (versym_scnndx == 0) 3848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengno .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section exist\n")); 3850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 3851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng check_versym (ebl, versym_scnndx); 3852441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check for duplicate index numbers. */ 3854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng do 3855441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3856cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct version_namelist *runp = version_namelist->next; 3857cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (runp != NULL) 3858441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 3859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (version_namelist->ndx == runp->ndx) 3860cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("duplicate version index %d\n"), 3862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int) version_namelist->ndx); 3863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3864cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng runp = runp->next; 3866441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3868cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct version_namelist *old = version_namelist; 3869cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng version_namelist = version_namelist->next; 3870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (old); 3871441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 3872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (version_namelist != NULL); 3873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3874cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (versym_scnndx != 0) 3875cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng.gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n")); 3877441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3878cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (hash_idx != 0 && gnu_hash_idx != 0) 3879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng compare_hash_gnu_hash (ebl, ehdr, hash_idx, gnu_hash_idx); 3880441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3881cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (scnref); 3882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 3883441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic GElf_Off 3886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_note_data (Ebl *ebl, const GElf_Ehdr *ehdr, 3887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data, int shndx, int phndx, GElf_Off start) 3888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 3889cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t offset = 0; 3890cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t last_offset = 0; 3891cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Nhdr nhdr; 3892cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t name_offset; 3893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t desc_offset; 3894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (offset < data->d_size 3895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (offset = gelf_getnote (data, offset, 3896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &nhdr, &name_offset, &desc_offset)) > 0) 3897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng last_offset = offset; 3899441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3900441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Make sure it is one of the note types we know about. */ 3901441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_type == ET_CORE) 3902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (nhdr.n_type) 3903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_PRSTATUS: 3905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_FPREGSET: 3906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_PRPSINFO: 3907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_TASKSTRUCT: /* NT_PRXREG on Solaris. */ 3908cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_PLATFORM: 3909cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_AUXV: 3910cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_GWINDOWS: 3911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_ASRS: 3912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_PSTATUS: 3913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_PSINFO: 3914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_PRCRED: 3915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_UTSNAME: 3916cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_LWPSTATUS: 3917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_LWPSINFO: 3918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_PRFPXREG: 3919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Known type. */ 3920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3921cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 3923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shndx == 0) 3924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengphdr[%d]: unknown core file note type %" PRIu32 " at offset %" PRIu64 "\n"), 3926cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phndx, (uint32_t) nhdr.n_type, start + offset); 3927cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 3928cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': unknown core file note type %" PRIu32 3930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng " at offset %Zu\n"), 3931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shndx, section_name (ebl, shndx), 3932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint32_t) nhdr.n_type, offset); 3933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 3935cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (nhdr.n_type) 3936cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 3937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_GNU_ABI_TAG: 3938cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_GNU_HWCAP: 3939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case NT_GNU_BUILD_ID: 3940cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 3941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3942cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 0: 3943cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Linux vDSOs use a type 0 note for the kernel version word. */ 3944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (nhdr.n_namesz == sizeof "Linux" 3945cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && !memcmp (data->d_buf + name_offset, "Linux", sizeof "Linux")) 3946441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 3947441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 3949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shndx == 0) 3950441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 3951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengphdr[%d]: unknown object file note type %" PRIu32 " at offset %Zu\n"), 3952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phndx, (uint32_t) nhdr.n_type, offset); 3953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 3954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': unknown object file note type %" PRIu32 3956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng " at offset %Zu\n"), 3957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shndx, section_name (ebl, shndx), 3958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint32_t) nhdr.n_type, offset); 3959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 3961441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return last_offset; 3963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 3964441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3965cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 3966cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt) 3967cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 3968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL 3969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 3970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 3971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengphdr[%d]: no note entries defined for the type of file\n"), 3972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt); 3973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (is_debuginfo) 3975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The p_offset values in a separate debug file are bogus. */ 3976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 3977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr->p_filesz == 0) 3979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 3980441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Off notes_size = 0; 3982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata_rawchunk (ebl->elf, 3983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdr->p_offset, phdr->p_filesz, 3984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_T_NHDR); 3985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data != NULL) 3986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng notes_size = check_note_data (ebl, ehdr, data, 0, cnt, phdr->p_offset); 3987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 3988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (notes_size == 0) 3989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("phdr[%d]: cannot get content of note section: %s\n"), 3990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, elf_errmsg (-1)); 3991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (notes_size != phdr->p_filesz) 3992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("phdr[%d]: extra %" PRIu64 " bytes after last note\n"), 3993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, phdr->p_filesz - notes_size); 3994441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 3995441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 3996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 3997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcheck_note_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) 3998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 3999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_size == 0) 4000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 4001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 4002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); 4003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 4004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 4005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), 4006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 4007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return; 4008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 4009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 4010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL 4011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 4012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 4013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsection [%2d] '%s': no note entries defined for the type of file\n"), 4014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 4015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 4016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Off notes_size = check_note_data (ebl, ehdr, data, idx, 0, 0); 4017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 4018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (notes_size == 0) 4019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': cannot get content of note section\n"), 4020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx)); 4021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (notes_size != shdr->sh_size) 4022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("section [%2d] '%s': extra %" PRIu64 4023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng " bytes after last note\n"), 4024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng idx, section_name (ebl, idx), shdr->sh_size - notes_size); 4025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 4026441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4027441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 4028441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectcheck_program_header (Ebl *ebl, GElf_Ehdr *ehdr) 4029441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 4030441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_phoff == 0) 4031441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return; 4032441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4033441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN 4034441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && ehdr->e_type != ET_CORE) 4035441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 4036441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectonly executables, shared objects, and core files can have program headers\n")); 4037441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4038441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int num_pt_interp = 0; 4039441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int num_pt_tls = 0; 4040441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int num_pt_relro = 0; 4041441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4042441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (int cnt = 0; cnt < ehdr->e_phnum; ++cnt) 4043441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4044441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Phdr phdr_mem; 4045441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Phdr *phdr; 4046441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4047441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem); 4048441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (phdr == NULL) 4049441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4050441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("cannot get program header entry %d: %s\n"), 4051441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cnt, elf_errmsg (-1)); 4052441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 4053441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4054441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4055441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME 4056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO 4057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check for a known machine-specific type. */ 4058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL) 4059441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 4060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprogram header entry %d: unknown program header entry type %#" PRIx64 "\n"), 4061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, (uint64_t) phdr->p_type); 4062441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4063441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (phdr->p_type == PT_LOAD) 4064441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project has_loadable_segment = true; 4065441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (phdr->p_type == PT_INTERP) 4066441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4067441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (++num_pt_interp != 1) 4068441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4069441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (num_pt_interp == 2) 4070441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 4071441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmore than one INTERP entry in program header\n")); 4072441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4073441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project has_interp_segment = true; 4074441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4075441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (phdr->p_type == PT_TLS) 4076441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4077441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (++num_pt_tls == 2) 4078441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("more than one TLS entry in program header\n")); 4079441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4080441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (phdr->p_type == PT_NOTE) 4081441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project check_note (ebl, ehdr, phdr, cnt); 4082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (phdr->p_type == PT_DYNAMIC) 4083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 4084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr->e_type == ET_EXEC && ! has_interp_segment) 4085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 4086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic executable cannot have dynamic sections\n")); 4087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 4088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 4089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that the .dynamic section, if it exists, has 4090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the same address. */ 4091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = NULL; 4092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 4093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 4094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 4095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 4096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC) 4097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 4098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr->p_offset != shdr->sh_offset) 4099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 4100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdynamic section reference in program header has wrong offset\n")); 4101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr->p_memsz != shdr->sh_size) 4102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 4103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdynamic section size mismatch in program and section header\n")); 4104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 4105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 4106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 4107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 4108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 4109441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if (phdr->p_type == PT_GNU_RELRO) 4110441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4111441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (++num_pt_relro == 2) 4112441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 4113441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectmore than one GNU_RELRO entry in program header\n")); 4114441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 4115441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4116441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check that the region is in a writable segment. */ 4117441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project int inner; 4118441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project for (inner = 0; inner < ehdr->e_phnum; ++inner) 4119441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4120441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Phdr phdr2_mem; 4121441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Phdr *phdr2; 4122441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem); 4124441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (phdr2 == NULL) 4125441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project continue; 4126441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4127441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (phdr2->p_type == PT_LOAD 4128441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && phdr->p_vaddr >= phdr2->p_vaddr 4129441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project && (phdr->p_vaddr + phdr->p_memsz 4130441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project <= phdr2->p_vaddr + phdr2->p_memsz)) 4131441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4132441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if ((phdr2->p_flags & PF_W) == 0) 4133441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 4134441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectloadable segment GNU_RELRO applies to is not writable\n")); 4135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((phdr2->p_flags &~ PF_W) != (phdr->p_flags &~ PF_W)) 4136441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 4137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengloadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"), 4138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cnt, inner); 4139441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project break; 4140441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4141441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4142441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4143441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (inner >= ehdr->e_phnum) 4144441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 4145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng%s segment not contained in a loaded segment\n"), "GNU_RELRO"); 4146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 4147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 4148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (phdr->p_type == PT_PHDR) 4149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 4150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that the region is in a writable segment. */ 4151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int inner; 4152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (inner = 0; inner < ehdr->e_phnum; ++inner) 4153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 4154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr2_mem; 4155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr2; 4156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 4157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem); 4158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr2 != NULL 4159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && phdr2->p_type == PT_LOAD 4160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && phdr->p_vaddr >= phdr2->p_vaddr 4161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (phdr->p_vaddr + phdr->p_memsz 4162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng <= phdr2->p_vaddr + phdr2->p_memsz)) 4163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 4164441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 4166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (inner >= ehdr->e_phnum) 4167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 4168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng%s segment not contained in a loaded segment\n"), "PHDR"); 4169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 4170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Check that offset in segment corresponds to offset in ELF 4171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng header. */ 4172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr->p_offset != ehdr->e_phoff) 4173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("\ 4174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprogram header offset in ELF header and PHDR entry do not match")); 4175441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4176441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr->p_filesz > phdr->p_memsz 4178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (phdr->p_memsz != 0 || phdr->p_type != PT_NOTE)) 4179441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 4180441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprogram header entry %d: file size greater than memory size\n"), 4181441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project cnt); 4182441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4183441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (phdr->p_align > 1) 4184441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4185441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (!powerof2 (phdr->p_align)) 4186441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 4187441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprogram header entry %d: alignment not a power of 2\n"), cnt); 4188441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0) 4189441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("\ 4190441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprogram header entry %d: file offset and virtual address not module of alignment\n"), cnt); 4191441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4192441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4193441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 4194441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4195441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4196441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project/* Process one file. */ 4197441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectstatic void 4198441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Projectprocess_elf_file (Elf *elf, const char *prefix, const char *suffix, 4199441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project const char *fname, size_t size, bool only_one) 4200441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project{ 4201441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Reset variables. */ 4202441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ndynamic = 0; 4203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nverneed = 0; 4204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nverdef = 0; 4205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng textrel = false; 4206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed_textrel = false; 4207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng has_loadable_segment = false; 4208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng has_interp_segment = false; 4209441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4210441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Ehdr ehdr_mem; 4211441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 4212441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project Ebl *ebl; 4213441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4214441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Print the file name. */ 4215441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (!only_one) 4216441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4217441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (prefix != NULL) 4218441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project printf ("\n%s(%s)%s:\n", prefix, fname, suffix); 4219441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project else 4220441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project printf ("\n%s:\n", fname); 4221441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4222441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4223441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project if (ehdr == NULL) 4224441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project { 4225441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ERROR (gettext ("cannot read ELF header: %s\n"), elf_errmsg (-1)); 4226441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project return; 4227441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project } 4228441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4229441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl = ebl_openbackend (elf); 4230441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* If there is no appropriate backend library we cannot test 4231441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project architecture and OS specific features. Any encountered extension 4232441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project is an error. */ 4233441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4234441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Go straight by the gABI, check all the parts in turn. */ 4235441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project check_elf_header (ebl, ehdr, size); 4236441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4237441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Check the program header. */ 4238441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project check_program_header (ebl, ehdr); 4239441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4240441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Next the section headers. It is OK if there are no section 4241441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project headers at all. */ 4242441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project check_sections (ebl, ehdr); 4243441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project 4244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Report if no relocation section needed the text relocation flag. */ 4245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (textrel && !needed_textrel) 4246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ERROR (gettext ("text relocation flag set but not needed\n")); 4247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 4248441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project /* Free the resources. */ 4249441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project ebl_closebackend (ebl); 4250441f72d43a9b550baa779fc82f70816da5f74f0eThe Android Open Source Project} 4251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 4252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 4253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "debugpred.h" 4254