1cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Compare relevant content of two ELF files. 2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc. 3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This file is part of Red Hat elfutils. 4cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Written by Ulrich Drepper <drepper@redhat.com>, 2005. 5cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 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. 9cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 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>. */ 26cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 27cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef HAVE_CONFIG_H 28cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# include <config.h> 29cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 30cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 31cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <argp.h> 32cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <assert.h> 33cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <errno.h> 34cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <error.h> 35cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <fcntl.h> 36cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <locale.h> 37cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <libintl.h> 38cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdbool.h> 39cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdio.h> 40cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdlib.h> 41cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <string.h> 42cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <unistd.h> 43cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 44cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libelf/elf-knowledge.h" 45cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "../libebl/libeblP.h" 46cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 47cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 48cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Prototypes of local functions. */ 49cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic Elf *open_file (const char *fname, int *fdp, Ebl **eblp); 50cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool search_for_copy_reloc (Ebl *ebl, size_t scnndx, int symndx); 51cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int regioncompare (const void *p1, const void *p2); 52cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 53cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 54cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Name and version of program. */ 55cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_version (FILE *stream, struct argp_state *state); 56cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengvoid (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; 57cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 58cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Bug report address. */ 59cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengconst char *argp_program_bug_address = PACKAGE_BUGREPORT; 60cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 61cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Values for the parameters which have no short form. */ 62cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define OPT_GAPS 0x100 63cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define OPT_HASH_INEXACT 0x101 64cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 65cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Definitions of arguments for argp functions. */ 66cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const struct argp_option options[] = 67cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 68cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { NULL, 0, NULL, 0, N_("Control options:"), 0 }, 69cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "gaps", OPT_GAPS, "ACTION", 0, N_("Control treatment of gaps in loadable segments [ignore|match] (default: ignore)"), 0 }, 70cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "hash-inexact", OPT_HASH_INEXACT, NULL, 0, 71cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng N_("Ignore permutation of buckets in SHT_HASH section"), 0 }, 72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { "quiet", 'q', NULL, 0, N_("Output nothing; yield exit status only"), 0 }, 73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 }, 75cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { NULL, 0, NULL, 0, NULL, 0 } 76cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Short description of program. */ 79cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char doc[] = N_("\ 80cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengCompare relevant parts of two ELF files for equality."); 81cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 82cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Strings for arguments in help texts. */ 83cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char args_doc[] = N_("FILE1 FILE2"); 84cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 85cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Prototype for option handler. */ 86cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic error_t parse_opt (int key, char *arg, struct argp_state *state); 87cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 88cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Data structure to communicate with argp functions. */ 89cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic struct argp argp = 90cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 91cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng options, parse_opt, args_doc, doc, NULL, NULL, NULL 92cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 93cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 94cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 95cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* How to treat gaps in loadable segments. */ 96cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic enum 97cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 98cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gaps_ignore = 0, 99cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gaps_match 100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gaps; 102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Structure to hold information about used regions. */ 104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct region 105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr from; 107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr to; 108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct region *next; 109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Nonzero if only exit status is wanted. */ 112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool quiet; 113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* True iff SHT_HASH treatment should be generous. */ 115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool hash_inexact; 116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool hash_content_equivalent (size_t entsize, Elf_Data *, Elf_Data *); 118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengint 121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengmain (int argc, char *argv[]) 122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Set locale. */ 124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (void) setlocale (LC_ALL, ""); 125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure the message catalog can be found. */ 127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR); 128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Initialize the message catalog. */ 130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (void) textdomain (PACKAGE_TARNAME); 131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Parse and process arguments. */ 133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int remaining; 134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL); 135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We expect exactly two non-option parameters. */ 137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (remaining + 2 != argc)) 138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fputs (gettext ("Invalid number of parameters.\n"), stderr); 140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name); 141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exit (1); 142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Comparing the files is done in two phases: 145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1. compare all sections. Sections which are irrelevant (i.e., if 146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng strip would remove them) are ignored. Some section types are 147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng handled special. 148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 2. all parts of the loadable segments which are not parts of any 149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng section is compared according to the rules of the --gaps option. 150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng */ 151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int result = 0; 152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_version (EV_CURRENT); 153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *const fname1 = argv[remaining]; 155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int fd1; 156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Ebl *ebl1; 157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *elf1 = open_file (fname1, &fd1, &ebl1); 158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *const fname2 = argv[remaining + 1]; 160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int fd2; 161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Ebl *ebl2; 162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *elf2 = open_file (fname2, &fd2, &ebl2); 163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr ehdr1_mem; 165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr *ehdr1 = gelf_getehdr (elf1, &ehdr1_mem); 166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr1 == NULL) 167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, gettext ("cannot get ELF header of '%s': %s"), 168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, elf_errmsg (-1)); 169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr ehdr2_mem; 170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr *ehdr2 = gelf_getehdr (elf2, &ehdr2_mem); 171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr2 == NULL) 172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, gettext ("cannot get ELF header of '%s': %s"), 173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname2, elf_errmsg (-1)); 174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Compare the ELF headers. */ 176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (memcmp (ehdr1->e_ident, ehdr2->e_ident, EI_NIDENT) != 0 177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ehdr1->e_type != ehdr2->e_type 178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ehdr1->e_machine != ehdr2->e_machine 179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ehdr1->e_version != ehdr2->e_version 180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ehdr1->e_entry != ehdr2->e_entry 181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ehdr1->e_phoff != ehdr2->e_phoff 182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ehdr1->e_flags != ehdr2->e_flags 183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ehdr1->e_ehsize != ehdr2->e_ehsize 184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ehdr1->e_phentsize != ehdr2->e_phentsize 185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ehdr1->e_phnum != ehdr2->e_phnum 186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ehdr1->e_shentsize != ehdr2->e_shentsize)) 187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (! quiet) 189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, gettext ("%s %s diff: ELF header"), fname1, fname2); 190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = 1; 191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto out; 192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Iterate over all sections. We expect the sections in the two 195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng files to match exactly. */ 196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn1 = NULL; 197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn2 = NULL; 198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct region *regions = NULL; 199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t nregions = 0; 200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (1) 201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr1_mem; 203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr1; 204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *sname1 = NULL; 205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng do 206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng scn1 = elf_nextscn (elf1, scn1); 208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr1 = gelf_getshdr (scn1, &shdr1_mem); 209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr1 != NULL) 210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sname1 = elf_strptr (elf1, ehdr1->e_shstrndx, shdr1->sh_name); 211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (scn1 != NULL 213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ebl_section_strip_p (ebl1, ehdr1, shdr1, sname1, true, false)); 214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr2_mem; 216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr2; 217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *sname2 = NULL; 218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng do 219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng scn2 = elf_nextscn (elf2, scn2); 221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng shdr2 = gelf_getshdr (scn2, &shdr2_mem); 222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr2 != NULL) 223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sname2 = elf_strptr (elf2, ehdr2->e_shstrndx, shdr2->sh_name); 224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (scn2 != NULL 226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ebl_section_strip_p (ebl2, ehdr2, shdr2, sname2, true, false)); 227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (scn1 == NULL || scn2 == NULL) 229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (gaps != gaps_ignore && (shdr1->sh_flags & SHF_ALLOC) != 0) 232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct region *newp = (struct region *) alloca (sizeof (*newp)); 234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newp->from = shdr1->sh_offset; 235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newp->to = shdr1->sh_offset + shdr1->sh_size; 236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng newp->next = regions; 237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng regions = newp; 238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++nregions; 240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Compare the headers. We allow the name to be at a different 243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng location. */ 244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (strcmp (sname1, sname2) != 0)) 245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng header_mismatch: 247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, gettext ("%s %s differ: section header"), 248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, fname2); 249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = 1; 250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto out; 251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We ignore certain sections. */ 254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strcmp (sname1, ".gnu_debuglink") == 0 255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || strcmp (sname1, ".gnu.prelink_undo") == 0) 256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr1->sh_type != shdr2->sh_type 259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng // XXX Any flags which should be ignored? 260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || shdr1->sh_flags != shdr2->sh_flags 261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || shdr1->sh_addr != shdr2->sh_addr 262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (shdr1->sh_offset != shdr2->sh_offset 263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (shdr1->sh_flags & SHF_ALLOC) 264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ehdr1->e_type != ET_REL) 265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || shdr1->sh_size != shdr2->sh_size 266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || shdr1->sh_link != shdr2->sh_link 267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || shdr1->sh_info != shdr2->sh_info 268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || shdr1->sh_addralign != shdr2->sh_addralign 269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || shdr1->sh_entsize != shdr2->sh_entsize) 270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto header_mismatch; 271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data1 = elf_getdata (scn1, NULL); 273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data1 == NULL) 274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("cannot get content of section %zu in '%s': %s"), 276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_ndxscn (scn1), fname1, elf_errmsg (-1)); 277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data2 = elf_getdata (scn2, NULL); 279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data2 == NULL) 280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("cannot get content of section %zu in '%s': %s"), 282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_ndxscn (scn2), fname2, elf_errmsg (-1)); 283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (shdr1->sh_type) 285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_DYNSYM: 287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case SHT_SYMTAB: 288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Iterate over the symbol table. We ignore the st_size 289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng value of undefined symbols. */ 290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int ndx = 0; ndx < (int) (shdr1->sh_size / shdr1->sh_entsize); 291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++ndx) 292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym1_mem; 294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym1 = gelf_getsym (data1, ndx, &sym1_mem); 295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym1 == NULL) 296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("cannot get symbol in '%s': %s"), 298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, elf_errmsg (-1)); 299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym sym2_mem; 300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Sym *sym2 = gelf_getsym (data2, ndx, &sym2_mem); 301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym2 == NULL) 302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("cannot get symbol in '%s': %s"), 304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname2, elf_errmsg (-1)); 305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name1 = elf_strptr (elf1, shdr1->sh_link, 307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym1->st_name); 308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name2 = elf_strptr (elf2, shdr2->sh_link, 309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sym2->st_name); 310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (strcmp (name1, name2) != 0 311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || sym1->st_value != sym2->st_value 312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (sym1->st_size != sym2->st_size 313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && sym1->st_shndx != SHN_UNDEF) 314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || sym1->st_info != sym2->st_info 315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || sym1->st_other != sym2->st_other 316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || sym1->st_shndx != sym1->st_shndx)) 317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng // XXX Do we want to allow reordered symbol tables? 319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symtab_mismatch: 320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (! quiet) 321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elf_ndxscn (scn1) == elf_ndxscn (scn2)) 323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, 324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("%s %s differ: symbol table [%zu]"), 325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, fname2, elf_ndxscn (scn1)); 326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, gettext ("\ 328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng%s %s differ: symbol table [%zu,%zu]"), 329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, fname2, elf_ndxscn (scn1), 330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_ndxscn (scn2)); 331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = 1; 333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto out; 334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (sym1->st_shndx == SHN_UNDEF 337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && sym1->st_size != sym2->st_size) 338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The size of the symbol in the object defining it 340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng might have changed. That is OK unless the symbol 341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng is used in a copy relocation. Look over the 342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng sections in both files and determine which 343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng relocation section uses this symbol table 344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng section. Then look through the relocations to 345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng see whether any copy relocation references this 346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng symbol. */ 347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (search_for_copy_reloc (ebl1, elf_ndxscn (scn1), ndx) 348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || search_for_copy_reloc (ebl2, elf_ndxscn (scn2), ndx)) 349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto symtab_mismatch; 350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Compare the section content byte for byte. */ 356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (shdr1->sh_type == SHT_NOBITS 357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (data1->d_buf != NULL || data1->d_size == 0)); 358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (shdr2->sh_type == SHT_NOBITS 359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (data2->d_buf != NULL || data1->d_size == 0)); 360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (data1->d_size != data2->d_size 362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (shdr1->sh_type != SHT_NOBITS 363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && memcmp (data1->d_buf, data2->d_buf, 364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng data1->d_size) != 0))) 365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (hash_inexact 367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && shdr1->sh_type == SHT_HASH 368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && data1->d_size == data2->d_size 369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && hash_content_equivalent (shdr1->sh_entsize, data1, data2)) 370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (! quiet) 373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elf_ndxscn (scn1) == elf_ndxscn (scn2)) 375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, gettext ("\ 376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng%s %s differ: section [%zu] '%s' content"), 377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, fname2, elf_ndxscn (scn1), sname1); 378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, gettext ("\ 380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng%s %s differ: section [%zu,%zu] '%s' content"), 381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, fname2, elf_ndxscn (scn1), 382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_ndxscn (scn2), sname1); 383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = 1; 385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto out; 386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (scn1 != scn2)) 392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (! quiet) 394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, 395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("%s %s differ: unequal amount of important sections"), 396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, fname2); 397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = 1; 398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto out; 399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We we look at gaps, create artificial ones for the parts of the 402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng program which we are not in sections. */ 403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct region ehdr_region; 404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct region phdr_region; 405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (gaps != gaps_ignore) 406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ehdr_region.from = 0; 408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ehdr_region.to = ehdr1->e_ehsize; 409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ehdr_region.next = &phdr_region; 410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdr_region.from = ehdr1->e_phoff; 412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdr_region.to = ehdr1->e_phoff + ehdr1->e_phnum * ehdr1->e_phentsize; 413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdr_region.next = regions; 414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng regions = &ehdr_region; 416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nregions += 2; 417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If we need to look at the gaps we need access to the file data. */ 420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *raw1 = NULL; 421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t size1 = 0; 422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *raw2 = NULL; 423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t size2 = 0; 424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct region *regionsarr = alloca (nregions * sizeof (struct region)); 425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (gaps != gaps_ignore) 426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng raw1 = elf_rawfile (elf1, &size1); 428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (raw1 == NULL ) 429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, gettext ("cannot load data of '%s': %s"), 430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, elf_errmsg (-1)); 431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng raw2 = elf_rawfile (elf2, &size2); 433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (raw2 == NULL ) 434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, gettext ("cannot load data of '%s': %s"), 435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname2, elf_errmsg (-1)); 436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t cnt = 0; cnt < nregions; ++cnt) 438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng regionsarr[cnt] = *regions; 440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng regions = regions->next; 441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng qsort (regionsarr, nregions, sizeof (regionsarr[0]), regioncompare); 444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Compare the program header tables. */ 447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int ndx = 0; ndx < ehdr1->e_phnum; ++ndx) 448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr1_mem; 450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr1 = gelf_getphdr (elf1, ndx, &phdr1_mem); 451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr1 == NULL) 452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("cannot get program header entry %d of '%s': %s"), 454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ndx, fname1, elf_errmsg (-1)); 455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr2_mem; 456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr2 = gelf_getphdr (elf2, ndx, &phdr2_mem); 457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr2 == NULL) 458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("cannot get program header entry %d of '%s': %s"), 460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ndx, fname2, elf_errmsg (-1)); 461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (memcmp (phdr1, phdr2, sizeof (GElf_Phdr)) != 0)) 463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (! quiet) 465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, gettext ("%s %s differ: program header %d"), 466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, fname2, ndx); 467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = 1; 468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto out; 469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (gaps != gaps_ignore && phdr1->p_type == PT_LOAD) 472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t cnt = 0; 474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (cnt < nregions && regionsarr[cnt].to < phdr1->p_offset) 475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++cnt; 476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Off last = phdr1->p_offset; 478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Off end = phdr1->p_offset + phdr1->p_filesz; 479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (cnt < nregions && regionsarr[cnt].from < end) 480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (last < regionsarr[cnt].from) 482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Compare the [LAST,FROM) region. */ 484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (gaps == gaps_match); 485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (memcmp (raw1 + last, raw2 + last, 486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng regionsarr[cnt].from - last) != 0)) 487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gapmismatch: 489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!quiet) 490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (0, 0, gettext ("%s %s differ: gap"), 491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname1, fname2); 492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng result = 1; 493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto out; 494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng last = regionsarr[cnt].to; 498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++cnt; 499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (cnt == nregions && last < end) 502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng goto gapmismatch; 503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng out: 507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_end (elf1); 508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_end (elf2); 509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng close (fd1); 510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng close (fd2); 511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return result; 513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Print the version information. */ 517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void 518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fprintf (stream, "elfcmp (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fprintf (stream, gettext ("\ 522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengCopyright (C) %s Red Hat, Inc.\n\ 523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengThis is free software; see the source for copying conditions. There is NO\n\ 524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng"), "2008"); 526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); 527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Handle program arguments. */ 531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic error_t 532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengparse_opt (int key, char *arg, 533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct argp_state *state __attribute__ ((unused))) 534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (key) 536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 'q': 538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng quiet = true; 539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case OPT_GAPS: 542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (strcasecmp (arg, "ignore") == 0) 543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gaps = gaps_ignore; 544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (likely (strcasecmp (arg, "match") == 0)) 545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gaps = gaps_match; 546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fprintf (stderr, 549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("Invalid value '%s' for --gaps parameter."), 550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng arg); 551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng argp_help (&argp, stderr, ARGP_HELP_SEE, 552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng program_invocation_short_name); 553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exit (1); 554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case OPT_HASH_INEXACT: 558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng hash_inexact = true; 559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return ARGP_ERR_UNKNOWN; 563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic Elf * 569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengopen_file (const char *fname, int *fdp, Ebl **eblp) 570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int fd = open (fname, O_RDONLY); 572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (fd == -1)) 573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, errno, gettext ("cannot open '%s'"), fname); 574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); 575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elf == NULL) 576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("cannot create ELF descriptor for '%s': %s"), 578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fname, elf_errmsg (-1)); 579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Ebl *ebl = ebl_openbackend (elf); 580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ebl == NULL) 581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("cannot create EBL descriptor for '%s'"), fname); 583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *fdp = fd; 585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *eblp = ebl; 586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return elf; 587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool 591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengsearch_for_copy_reloc (Ebl *ebl, size_t scnndx, int symndx) 592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = NULL; 594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) 595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr shdr_mem; 597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr == NULL) 599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("cannot get section header of section %zu: %s"), 601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_ndxscn (scn), elf_errmsg (-1)); 602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((shdr->sh_type != SHT_REL && shdr->sh_type != SHT_RELA) 604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || shdr->sh_link != scnndx) 605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata (scn, NULL); 608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, 610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng gettext ("cannot get content of section %zu: %s"), 611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_ndxscn (scn), elf_errmsg (-1)); 612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (shdr->sh_type == SHT_REL) 614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int ndx = 0; ndx < (int) (shdr->sh_size / shdr->sh_entsize); 615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++ndx) 616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel rel_mem; 618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rel *rel = gelf_getrel (data, ndx, &rel_mem); 619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (rel == NULL) 620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, gettext ("cannot get relocation: %s"), 621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_errmsg (-1)); 622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((int) GELF_R_SYM (rel->r_info) == symndx 624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info))) 625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (int ndx = 0; ndx < (int) (shdr->sh_size / shdr->sh_entsize); 629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++ndx) 630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela rela_mem; 632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Rela *rela = gelf_getrela (data, ndx, &rela_mem); 633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (rela == NULL) 634cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng error (EXIT_FAILURE, 0, gettext ("cannot get relocation: %s"), 635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elf_errmsg (-1)); 636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((int) GELF_R_SYM (rela->r_info) == symndx 638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info))) 639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengregioncompare (const void *p1, const void *p2) 649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct region *r1 = (const struct region *) p1; 651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const struct region *r2 = (const struct region *) p2; 652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r1->from < r2->from) 654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 1; 656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_Elf32_Word (const void *p1, const void *p2) 661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf32_Word *w1 = p1; 663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf32_Word *w2 = p2; 664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (sizeof (int) >= sizeof (*w1)); 665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (int) *w1 - (int) *w2; 666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcompare_Elf64_Xword (const void *p1, const void *p2) 670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf64_Xword *w1 = p1; 672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf64_Xword *w2 = p2; 673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *w1 < *w2 ? -1 : *w1 > *w2 ? 1 : 0; 674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool 677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenghash_content_equivalent (size_t entsize, Elf_Data *data1, Elf_Data *data2) 678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define CHECK_HASH(Hash_Word) \ 680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { \ 681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Hash_Word *const hash1 = data1->d_buf; \ 682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Hash_Word *const hash2 = data2->d_buf; \ 683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t nbucket = hash1[0]; \ 684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t nchain = hash1[1]; \ 685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data1->d_size != (2 + nbucket + nchain) * sizeof hash1[0] \ 686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || hash2[0] != nbucket || hash2[1] != nchain) \ 687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; \ 688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Hash_Word *const bucket1 = &hash1[2]; \ 690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Hash_Word *const chain1 = &bucket1[nbucket]; \ 691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Hash_Word *const bucket2 = &hash2[2]; \ 692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Hash_Word *const chain2 = &bucket2[nbucket]; \ 693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool chain_ok[nchain]; \ 695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Hash_Word temp1[nchain - 1]; \ 696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Hash_Word temp2[nchain - 1]; \ 697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memset (chain_ok, 0, sizeof chain_ok); \ 698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < nbucket; ++i) \ 699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { \ 700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (bucket1[i] >= nchain || bucket2[i] >= nchain) \ 701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; \ 702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t b1 = 0; \ 704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t p = bucket1[i]; p != STN_UNDEF; p = chain1[p]) \ 705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (p >= nchain || b1 >= nchain - 1) \ 706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; \ 707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else \ 708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng temp1[b1++] = p; \ 709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t b2 = 0; \ 711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t p = bucket2[i]; p != STN_UNDEF; p = chain2[p]) \ 712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (p >= nchain || b2 >= nchain - 1) \ 713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; \ 714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else \ 715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng temp2[b2++] = p; \ 716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (b1 != b2) \ 718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; \ 719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng qsort (temp1, b1, sizeof temp1[0], compare_##Hash_Word); \ 721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng qsort (temp2, b2, sizeof temp2[0], compare_##Hash_Word); \ 722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (b1 = 0; b1 < b2; ++b1) \ 724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (temp1[b1] != temp2[b1]) \ 725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; \ 726cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else \ 727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng chain_ok[temp1[b1]] = true; \ 728cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } \ 729cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 730cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < nchain; ++i) \ 731cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!chain_ok[i] && chain1[i] != chain2[i]) \ 732cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; \ 733cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng \ 734cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; \ 735cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 736cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (entsize) 738cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 739cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 4: 740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CHECK_HASH (Elf32_Word); 741cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 742cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case 8: 743cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng CHECK_HASH (Elf64_Xword); 744cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "debugpred.h" 752