1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Compare relevant content of two ELF files.
20d528f9ceff2b96c521cefd75fc62d7151e3e6b1Mark Wielaard   Copyright (C) 2005-2012, 2014, 2015 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of the GNU General Public License as published by
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the Free Software Foundation; either version 3 of the License, or
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   (at your option) any later version.
10361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
12361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   GNU General Public License for more details.
15361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received a copy of the GNU General Public License
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
19b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifdef HAVE_CONFIG_H
20b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper# include <config.h>
21b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
22b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
23b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <argp.h>
24b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <assert.h>
25b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <errno.h>
26b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <error.h>
27b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <fcntl.h>
28f9ece8a9ee7c170c867189b6b2dd9f94124734beRoland McGrath#include <locale.h>
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libintl.h>
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdbool.h>
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdio.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h>
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h>
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <unistd.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
36fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich Drepper#include <system.h>
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "../libelf/elf-knowledge.h"
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "../libebl/libeblP.h"
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Prototypes of local functions.  */
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic Elf *open_file (const char *fname, int *fdp, Ebl **eblp);
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool search_for_copy_reloc (Ebl *ebl, size_t scnndx, int symndx);
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic  int regioncompare (const void *p1, const void *p2);
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Name and version of program.  */
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void print_version (FILE *stream, struct argp_state *state);
49fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Bug report address.  */
52fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Values for the parameters which have no short form.  */
554be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath#define OPT_GAPS		0x100
564be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath#define OPT_HASH_INEXACT	0x101
571fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath#define OPT_IGNORE_BUILD_ID	0x102
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Definitions of arguments for argp functions.  */
60b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const struct argp_option options[] =
61b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, N_("Control options:"), 0 },
634a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath  { "verbose", 'l', NULL, 0,
644a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath    N_("Output all differences, not just the first"), 0 },
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "gaps", OPT_GAPS, "ACTION", 0, N_("Control treatment of gaps in loadable segments [ignore|match] (default: ignore)"), 0 },
664be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  { "hash-inexact", OPT_HASH_INEXACT, NULL, 0,
674be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    N_("Ignore permutation of buckets in SHT_HASH section"), 0 },
681fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath  { "ignore-build-id", OPT_IGNORE_BUILD_ID, NULL, 0,
691fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath    N_("Ignore differences in build ID"), 0 },
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "quiet", 'q', NULL, 0, N_("Output nothing; yield exit status only"), 0 },
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, NULL, 0 }
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Short description of program.  */
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char doc[] = N_("\
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperCompare relevant parts of two ELF files for equality.");
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Strings for arguments in help texts.  */
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char args_doc[] = N_("FILE1 FILE2");
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Prototype for option handler.  */
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Data structure to communicate with argp functions.  */
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct argp argp =
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  options, parse_opt, args_doc, doc, NULL, NULL, NULL
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* How to treat gaps in loadable segments.  */
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic enum
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    gaps_ignore = 0,
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    gaps_match
98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  }
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  gaps;
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Structure to hold information about used regions.  */
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstruct region
103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Addr from;
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Addr to;
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct region *next;
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Nonzero if only exit status is wanted.  */
110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool quiet;
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1124a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath/* True iff multiple differences should be output.  */
1134a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrathstatic bool verbose;
1144a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath
1154be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath/* True iff SHT_HASH treatment should be generous.  */
1164be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathstatic bool hash_inexact;
1174be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
1181fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath/* True iff build ID notes should be ignored.  */
1191fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrathstatic bool ignore_build_id;
1201fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath
1214be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathstatic bool hash_content_equivalent (size_t entsize, Elf_Data *, Elf_Data *);
1224be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermain (int argc, char *argv[])
126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Set locale.  */
128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (void) setlocale (LC_ALL, "");
129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Make sure the message catalog can be found.  */
131b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Initialize the message catalog.  */
134b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  (void) textdomain (PACKAGE_TARNAME);
135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Parse and process arguments.  */
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int remaining;
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We expect exactly two non-option parameters.  */
141e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper  if (unlikely (remaining + 2 != argc))
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      fputs (gettext ("Invalid number of parameters.\n"), stderr);
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name);
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      exit (1);
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1484a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath  if (quiet)
1494a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath    verbose = false;
1504a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath
151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Comparing the files is done in two phases:
152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     1. compare all sections.  Sections which are irrelevant (i.e., if
1533a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper	strip would remove them) are ignored.  Some section types are
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	handled special.
155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     2. all parts of the loadable segments which are not parts of any
1563a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper	section is compared according to the rules of the --gaps option.
157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  */
158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result = 0;
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_version (EV_CURRENT);
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const char *const fname1 = argv[remaining];
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int fd1;
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl1;
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *elf1 = open_file (fname1, &fd1, &ebl1);
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const char *const fname2 = argv[remaining + 1];
167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int fd2;
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl2;
169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *elf2 = open_file (fname2, &fd2, &ebl2);
170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr ehdr1_mem;
172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *ehdr1 = gelf_getehdr (elf1, &ehdr1_mem);
173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr1 == NULL)
1743614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath    error (2, 0, gettext ("cannot get ELF header of '%s': %s"),
175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   fname1, elf_errmsg (-1));
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr ehdr2_mem;
177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *ehdr2 = gelf_getehdr (elf2, &ehdr2_mem);
178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr2 == NULL)
1793614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath    error (2, 0, gettext ("cannot get ELF header of '%s': %s"),
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   fname2, elf_errmsg (-1));
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1824a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath#define DIFFERENCE							      \
1834a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath  do									      \
1844a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath    {									      \
1854a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      result = 1;							      \
1864a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      if (! verbose)							      \
1874a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	goto out;							      \
1884a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath    }									      \
1894a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath  while (0)
1904a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath
191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Compare the ELF headers.  */
192e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper  if (unlikely (memcmp (ehdr1->e_ident, ehdr2->e_ident, EI_NIDENT) != 0
193e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		|| ehdr1->e_type != ehdr2->e_type
194e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		|| ehdr1->e_machine != ehdr2->e_machine
195e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		|| ehdr1->e_version != ehdr2->e_version
196e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		|| ehdr1->e_entry != ehdr2->e_entry
197e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		|| ehdr1->e_phoff != ehdr2->e_phoff
198e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		|| ehdr1->e_flags != ehdr2->e_flags
199e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		|| ehdr1->e_ehsize != ehdr2->e_ehsize
200e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		|| ehdr1->e_phentsize != ehdr2->e_phentsize
201e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		|| ehdr1->e_phnum != ehdr2->e_phnum
202e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		|| ehdr1->e_shentsize != ehdr2->e_shentsize))
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (! quiet)
205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	error (0, 0, gettext ("%s %s diff: ELF header"), fname1, fname2);
2064a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      DIFFERENCE;
207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
209bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  size_t shnum1;
210bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  size_t shnum2;
211bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  if (unlikely (elf_getshdrnum (elf1, &shnum1) != 0))
212bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    error (2, 0, gettext ("cannot get section count of '%s': %s"),
213bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	   fname1, elf_errmsg (-1));
214bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  if (unlikely (elf_getshdrnum (elf2, &shnum2) != 0))
215bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    error (2, 0, gettext ("cannot get section count of '%s': %s"),
216bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	   fname2, elf_errmsg (-1));
217bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  if (unlikely (shnum1 != shnum2))
218bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    {
219bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      if (! quiet)
220bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	error (0, 0, gettext ("%s %s diff: section count"), fname1, fname2);
2214a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      DIFFERENCE;
222bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    }
223bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath
224bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  size_t phnum1;
225bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  size_t phnum2;
226bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  if (unlikely (elf_getphdrnum (elf1, &phnum1) != 0))
227bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    error (2, 0, gettext ("cannot get program header count of '%s': %s"),
228bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	   fname1, elf_errmsg (-1));
229bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  if (unlikely (elf_getphdrnum (elf2, &phnum2) != 0))
230bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    error (2, 0, gettext ("cannot get program header count of '%s': %s"),
231bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	   fname2, elf_errmsg (-1));
232bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  if (unlikely (phnum1 != phnum2))
233bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    {
234bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      if (! quiet)
235bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	error (0, 0, gettext ("%s %s diff: program header count"),
236bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath	       fname1, fname2);
2374a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      DIFFERENCE;
238bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath    }
239bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath
240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Iterate over all sections.  We expect the sections in the two
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     files to match exactly.  */
242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn1 = NULL;
243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn2 = NULL;
244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct region *regions = NULL;
245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t nregions = 0;
246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (1)
247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr shdr1_mem;
249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr *shdr1;
250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *sname1 = NULL;
251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      do
252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  scn1 = elf_nextscn (elf1, scn1);
254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr1 = gelf_getshdr (scn1, &shdr1_mem);
255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr1 != NULL)
256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    sname1 = elf_strptr (elf1, ehdr1->e_shstrndx, shdr1->sh_name);
257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      while (scn1 != NULL
259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     && ebl_section_strip_p (ebl1, ehdr1, shdr1, sname1, true, false));
260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr shdr2_mem;
262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr *shdr2;
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *sname2 = NULL;
264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      do
265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  scn2 = elf_nextscn (elf2, scn2);
267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  shdr2 = gelf_getshdr (scn2, &shdr2_mem);
268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr2 != NULL)
269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    sname2 = elf_strptr (elf2, ehdr2->e_shstrndx, shdr2->sh_name);
270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      while (scn2 != NULL
272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     && ebl_section_strip_p (ebl2, ehdr2, shdr2, sname2, true, false));
273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (scn1 == NULL || scn2 == NULL)
275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	break;
276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (gaps != gaps_ignore && (shdr1->sh_flags & SHF_ALLOC) != 0)
278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
279b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  struct region *newp = (struct region *) alloca (sizeof (*newp));
280b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  newp->from = shdr1->sh_offset;
281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  newp->to = shdr1->sh_offset + shdr1->sh_size;
282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  newp->next = regions;
283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  regions = newp;
284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ++nregions;
286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Compare the headers.  We allow the name to be at a different
289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 location.  */
290e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard      if (unlikely (sname1 == NULL || sname2 == NULL
291e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard		    || strcmp (sname1, sname2) != 0))
292b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2934a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	  error (0, 0, gettext ("%s %s differ: section [%zu], [%zu] name"),
2944a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		 fname1, fname2, elf_ndxscn (scn1), elf_ndxscn (scn2));
2954a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	  DIFFERENCE;
296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We ignore certain sections.  */
299e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard      if ((sname1 != NULL && strcmp (sname1, ".gnu_debuglink") == 0)
300e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard	  || (sname1 != NULL && strcmp (sname1, ".gnu.prelink_undo") == 0))
301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	continue;
302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr1->sh_type != shdr2->sh_type
304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX Any flags which should be ignored?
305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_flags != shdr2->sh_flags
306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_addr != shdr2->sh_addr
307059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  || (shdr1->sh_offset != shdr2->sh_offset
308059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      && (shdr1->sh_flags & SHF_ALLOC)
309059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      && ehdr1->e_type != ET_REL)
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_size != shdr2->sh_size
311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_link != shdr2->sh_link
312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_info != shdr2->sh_info
313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_addralign != shdr2->sh_addralign
314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_entsize != shdr2->sh_entsize)
3154a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	{
3164a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	  error (0, 0, gettext ("%s %s differ: section [%zu] '%s' header"),
3174a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		 fname1, fname2, elf_ndxscn (scn1), sname1);
3184a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	  DIFFERENCE;
3194a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	}
320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf_Data *data1 = elf_getdata (scn1, NULL);
322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data1 == NULL)
3233614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
324e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	       gettext ("cannot get content of section %zu in '%s': %s"),
325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_ndxscn (scn1), fname1, elf_errmsg (-1));
326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf_Data *data2 = elf_getdata (scn2, NULL);
328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data2 == NULL)
3293614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
330e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	       gettext ("cannot get content of section %zu in '%s': %s"),
331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_ndxscn (scn2), fname2, elf_errmsg (-1));
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      switch (shdr1->sh_type)
334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNSYM:
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_SYMTAB:
337e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard	  if (shdr1->sh_entsize == 0)
338e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard	    error (2, 0,
339e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard		   gettext ("symbol table [%zu] in '%s' has zero sh_entsize"),
340e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard		   elf_ndxscn (scn1), fname1);
341e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard
342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Iterate over the symbol table.  We ignore the st_size
343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     value of undefined symbols.  */
344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (int ndx = 0; ndx < (int) (shdr1->sh_size / shdr1->sh_entsize);
345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ++ndx)
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Sym sym1_mem;
348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Sym *sym1 = gelf_getsym (data1, ndx, &sym1_mem);
349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (sym1 == NULL)
3503614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath		error (2, 0,
351e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		       gettext ("cannot get symbol in '%s': %s"),
352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       fname1, elf_errmsg (-1));
353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Sym sym2_mem;
354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Sym *sym2 = gelf_getsym (data2, ndx, &sym2_mem);
355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (sym2 == NULL)
3563614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath		error (2, 0,
357e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		       gettext ("cannot get symbol in '%s': %s"),
358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       fname2, elf_errmsg (-1));
359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      const char *name1 = elf_strptr (elf1, shdr1->sh_link,
361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      sym1->st_name);
362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      const char *name2 = elf_strptr (elf2, shdr2->sh_link,
363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      sym2->st_name);
3645c1a45c2d370e7fd1149fa74a9382e202fbfe8feMark Wielaard	      if (unlikely (name1 == NULL || name2 == NULL
3655c1a45c2d370e7fd1149fa74a9382e202fbfe8feMark Wielaard			    || strcmp (name1, name2) != 0
366e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    || sym1->st_value != sym2->st_value
367e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    || (sym1->st_size != sym2->st_size
368e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper				&& sym1->st_shndx != SHN_UNDEF)
369e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    || sym1->st_info != sym2->st_info
370e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    || sym1->st_other != sym2->st_other
371e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    || sym1->st_shndx != sym1->st_shndx))
372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  // XXX Do we want to allow reordered symbol tables?
3747d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		symtab_mismatch:
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (! quiet)
3767d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		    {
3777d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		      if (elf_ndxscn (scn1) == elf_ndxscn (scn2))
3787d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			error (0, 0,
3797d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			       gettext ("%s %s differ: symbol table [%zu]"),
3807d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			       fname1, fname2, elf_ndxscn (scn1));
3817d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		      else
3827d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			error (0, 0, gettext ("\
3837d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper%s %s differ: symbol table [%zu,%zu]"),
3847d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			       fname1, fname2, elf_ndxscn (scn1),
3857d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			       elf_ndxscn (scn2));
3867d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		    }
3874a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		  DIFFERENCE;
3884a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		  break;
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (sym1->st_shndx == SHN_UNDEF
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && sym1->st_size != sym2->st_size)
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* The size of the symbol in the object defining it
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     might have changed.  That is OK unless the symbol
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     is used in a copy relocation.  Look over the
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     sections in both files and determine which
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     relocation section uses this symbol table
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     section.  Then look through the relocations to
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     see whether any copy relocation references this
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     symbol.  */
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (search_for_copy_reloc (ebl1, elf_ndxscn (scn1), ndx)
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      || search_for_copy_reloc (ebl2, elf_ndxscn (scn2), ndx))
4047d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		    goto symtab_mismatch;
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4091fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	case SHT_NOTE:
4101fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	  /* Parse the note format and compare the notes themselves.  */
4111fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	  {
4121fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    GElf_Nhdr note1;
4131fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    GElf_Nhdr note2;
4141fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath
4151fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    size_t off1 = 0;
4161fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    size_t off2 = 0;
4171fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    size_t name_offset;
4181fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    size_t desc_offset;
4191fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    while (off1 < data1->d_size
4201fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		   && (off1 = gelf_getnote (data1, off1, &note1,
4211fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath					    &name_offset, &desc_offset)) > 0)
4221fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	      {
4231fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		const char *name1 = data1->d_buf + name_offset;
4241fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		const void *desc1 = data1->d_buf + desc_offset;
4251fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (off2 >= data2->d_size)
4261fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  {
4271fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    if (! quiet)
4281fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      error (0, 0, gettext ("\
4291fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: section [%zu] '%s' number of notes"),
4301fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			     fname1, fname2, elf_ndxscn (scn1), sname1);
4314a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		    DIFFERENCE;
4321fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  }
4331fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		off2 = gelf_getnote (data2, off2, &note2,
4341fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath				     &name_offset, &desc_offset);
4351fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (off2 == 0)
4361fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  error (2, 0, gettext ("\
4371fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrathcannot read note section [%zu] '%s' in '%s': %s"),
4381fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			 elf_ndxscn (scn2), sname2, fname2, elf_errmsg (-1));
4391fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		const char *name2 = data2->d_buf + name_offset;
4401fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		const void *desc2 = data2->d_buf + desc_offset;
4411fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath
4421fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (note1.n_namesz != note2.n_namesz
4431fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    || memcmp (name1, name2, note1.n_namesz))
4441fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  {
4451fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    if (! quiet)
4461fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      error (0, 0, gettext ("\
4471fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: section [%zu] '%s' note name"),
4481fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			     fname1, fname2, elf_ndxscn (scn1), sname1);
4494a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		    DIFFERENCE;
4501fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  }
4511fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (note1.n_type != note2.n_type)
4521fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  {
4531fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    if (! quiet)
4541fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      error (0, 0, gettext ("\
4551fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: section [%zu] '%s' note '%s' type"),
4561fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			     fname1, fname2, elf_ndxscn (scn1), sname1, name1);
4574a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		    DIFFERENCE;
4581fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  }
4591fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (note1.n_descsz != note2.n_descsz
4601fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    || memcmp (desc1, desc2, note1.n_descsz))
4611fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  {
4621fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    if (note1.n_type == NT_GNU_BUILD_ID
4631fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			&& note1.n_namesz == sizeof "GNU"
4641fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			&& !memcmp (name1, "GNU", sizeof "GNU"))
4651fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      {
4661fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			if (note1.n_descsz != note2.n_descsz)
4671fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			  {
4681fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			    if (! quiet)
4691fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			      error (0, 0, gettext ("\
4701fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: build ID length"),
4711fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath				     fname1, fname2);
4724a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath			    DIFFERENCE;
4731fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			  }
4741fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			else if (! ignore_build_id)
4751fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			  {
4761fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			    if (! quiet)
4771fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			      error (0, 0, gettext ("\
4781fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: build ID content"),
4791fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath				     fname1, fname2);
4804a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath			    DIFFERENCE;
4811fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			  }
4821fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      }
4831fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    else
4841fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      {
4851fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			if (! quiet)
4861fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			  error (0, 0, gettext ("\
4871fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: section [%zu] '%s' note '%s' content"),
4881fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath				 fname1, fname2, elf_ndxscn (scn1), sname1,
4891fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath				 name1);
4904a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath			DIFFERENCE;
4911fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      }
4921fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  }
4931fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	      }
4941fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    if (off2 < data2->d_size)
4951fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	      {
4961fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (! quiet)
4971fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  error (0, 0, gettext ("\
4981fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: section [%zu] '%s' number of notes"),
4991fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			 fname1, fname2, elf_ndxscn (scn1), sname1);
5004a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		DIFFERENCE;
5011fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	      }
5021fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	  }
5031fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	  break;
5041fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath
505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	default:
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Compare the section content byte for byte.  */
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  assert (shdr1->sh_type == SHT_NOBITS
508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || (data1->d_buf != NULL || data1->d_size == 0));
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  assert (shdr2->sh_type == SHT_NOBITS
510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || (data2->d_buf != NULL || data1->d_size == 0));
511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
512e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	  if (unlikely (data1->d_size != data2->d_size
513e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			|| (shdr1->sh_type != SHT_NOBITS
5140d528f9ceff2b96c521cefd75fc62d7151e3e6b1Mark Wielaard			    && data1->d_size != 0
515e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    && memcmp (data1->d_buf, data2->d_buf,
516e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper				       data1->d_size) != 0)))
517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
5184be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	      if (hash_inexact
5194be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath		  && shdr1->sh_type == SHT_HASH
5204be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath		  && data1->d_size == data2->d_size
5214be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath		  && hash_content_equivalent (shdr1->sh_entsize, data1, data2))
5224be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath		break;
5234be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (! quiet)
5257d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		{
5267d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		  if (elf_ndxscn (scn1) == elf_ndxscn (scn2))
5277d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		    error (0, 0, gettext ("\
5287d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper%s %s differ: section [%zu] '%s' content"),
5297d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			   fname1, fname2, elf_ndxscn (scn1), sname1);
5307d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		  else
5317d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		    error (0, 0, gettext ("\
5327d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper%s %s differ: section [%zu,%zu] '%s' content"),
5337d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			   fname1, fname2, elf_ndxscn (scn1),
5347d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			   elf_ndxscn (scn2), sname1);
5357d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		}
5364a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	      DIFFERENCE;
537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
542e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper  if (unlikely (scn1 != scn2))
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (! quiet)
545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	error (0, 0,
546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       gettext ("%s %s differ: unequal amount of important sections"),
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       fname1, fname2);
5484a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      DIFFERENCE;
549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We we look at gaps, create artificial ones for the parts of the
552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     program which we are not in sections.  */
553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct region ehdr_region;
554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct region phdr_region;
555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (gaps != gaps_ignore)
556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ehdr_region.from = 0;
558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ehdr_region.to = ehdr1->e_ehsize;
559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ehdr_region.next = &phdr_region;
560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      phdr_region.from = ehdr1->e_phoff;
562bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      phdr_region.to = ehdr1->e_phoff + phnum1 * ehdr1->e_phentsize;
563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      phdr_region.next = regions;
564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      regions = &ehdr_region;
566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      nregions += 2;
567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If we need to look at the gaps we need access to the file data.  */
570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *raw1 = NULL;
571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t size1 = 0;
572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *raw2 = NULL;
573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t size2 = 0;
574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct region *regionsarr = alloca (nregions * sizeof (struct region));
575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (gaps != gaps_ignore)
576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      raw1 = elf_rawfile (elf1, &size1);
578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (raw1 == NULL )
5793614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0, gettext ("cannot load data of '%s': %s"),
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       fname1, elf_errmsg (-1));
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      raw2 = elf_rawfile (elf2, &size2);
583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (raw2 == NULL )
5843614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0, gettext ("cannot load data of '%s': %s"),
585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       fname2, elf_errmsg (-1));
586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (size_t cnt = 0; cnt < nregions; ++cnt)
588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  regionsarr[cnt] = *regions;
590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  regions = regions->next;
591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      qsort (regionsarr, nregions, sizeof (regionsarr[0]), regioncompare);
594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Compare the program header tables.  */
597bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  for (unsigned int ndx = 0; ndx < phnum1; ++ndx)
598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr phdr1_mem;
600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr *phdr1 = gelf_getphdr (elf1, ndx, &phdr1_mem);
601e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard      if (phdr1 == NULL)
6023614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
603e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	       gettext ("cannot get program header entry %d of '%s': %s"),
604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ndx, fname1, elf_errmsg (-1));
605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr phdr2_mem;
606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr *phdr2 = gelf_getphdr (elf2, ndx, &phdr2_mem);
607e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard      if (phdr2 == NULL)
6083614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
609e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	       gettext ("cannot get program header entry %d of '%s': %s"),
610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ndx, fname2, elf_errmsg (-1));
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
612e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper      if (unlikely (memcmp (phdr1, phdr2, sizeof (GElf_Phdr)) != 0))
613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (! quiet)
615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    error (0, 0, gettext ("%s %s differ: program header %d"),
616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   fname1, fname2, ndx);
6174a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	  DIFFERENCE;
618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (gaps != gaps_ignore && phdr1->p_type == PT_LOAD)
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t cnt = 0;
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  while (cnt < nregions && regionsarr[cnt].to < phdr1->p_offset)
624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ++cnt;
625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Off last = phdr1->p_offset;
627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Off end = phdr1->p_offset + phdr1->p_filesz;
628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  while (cnt < nregions && regionsarr[cnt].from < end)
629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (last < regionsarr[cnt].from)
631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Compare the [LAST,FROM) region.  */
633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  assert (gaps == gaps_match);
634e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		  if (unlikely (memcmp (raw1 + last, raw2 + last,
635e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper					regionsarr[cnt].from - last) != 0))
636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    gapmismatch:
638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (!quiet)
639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			error (0, 0, gettext ("%s %s differ: gap"),
640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       fname1, fname2);
6414a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		      DIFFERENCE;
6424a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		      break;
643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      last = regionsarr[cnt].to;
647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++cnt;
648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt == nregions && last < end)
651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    goto gapmismatch;
652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper out:
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_end (elf1);
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_end (elf2);
658095f53490bcf684a834d835ee8118f1d8ea51698Mark Wielaard  ebl_closebackend (ebl1);
659095f53490bcf684a834d835ee8118f1d8ea51698Mark Wielaard  ebl_closebackend (ebl2);
660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  close (fd1);
661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  close (fd2);
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print the version information.  */
668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
671b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  fprintf (stream, "elfcmp (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("\
673b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperCopyright (C) %s Red Hat, Inc.\n\
674b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperThis is free software; see the source for copying conditions.  There is NO\n\
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
6763a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper"), "2012");
677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle program arguments.  */
682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t
683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperparse_opt (int key, char *arg,
684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   struct argp_state *state __attribute__ ((unused)))
685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (key)
687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'q':
689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      quiet = true;
690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6924a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath    case 'l':
6934a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      verbose = true;
6944a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      break;
6954a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath
696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case OPT_GAPS:
697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (strcasecmp (arg, "ignore") == 0)
698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	gaps = gaps_ignore;
699e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper      else if (likely (strcasecmp (arg, "match") == 0))
700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	gaps = gaps_match;
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  fprintf (stderr,
704e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		   gettext ("Invalid value '%s' for --gaps parameter."),
705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   arg);
706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  argp_help (&argp, stderr, ARGP_HELP_SEE,
707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     program_invocation_short_name);
708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  exit (1);
709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
7124be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    case OPT_HASH_INEXACT:
7134be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      hash_inexact = true;
7144be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      break;
7154be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
7161fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath    case OPT_IGNORE_BUILD_ID:
7171fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath      ignore_build_id = true;
7181fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath      break;
7191fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath
720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ARGP_ERR_UNKNOWN;
722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic Elf *
728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperopen_file (const char *fname, int *fdp, Ebl **eblp)
729b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int fd = open (fname, O_RDONLY);
731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (unlikely (fd == -1))
7323614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath    error (2, errno, gettext ("cannot open '%s'"), fname);
733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf == NULL)
7353614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath    error (2, 0,
736e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	   gettext ("cannot create ELF descriptor for '%s': %s"),
737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   fname, elf_errmsg (-1));
738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl = ebl_openbackend (elf);
739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ebl == NULL)
7403614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath    error (2, 0,
741e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	   gettext ("cannot create EBL descriptor for '%s'"), fname);
742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *fdp = fd;
744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *eblp = ebl;
745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return elf;
746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersearch_for_copy_reloc (Ebl *ebl, size_t scnndx, int symndx)
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn = NULL;
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr shdr_mem;
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr == NULL)
7583614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       gettext ("cannot get section header of section %zu: %s"),
760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_ndxscn (scn), elf_errmsg (-1));
761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_type != SHT_REL && shdr->sh_type != SHT_RELA)
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr->sh_link != scnndx)
764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	continue;
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf_Data *data = elf_getdata (scn, NULL);
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data == NULL)
7683614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       gettext ("cannot get content of section %zu: %s"),
770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_ndxscn (scn), elf_errmsg (-1));
771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
772e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard      if (shdr->sh_type == SHT_REL && shdr->sh_entsize != 0)
773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	for (int ndx = 0; ndx < (int) (shdr->sh_size / shdr->sh_entsize);
774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     ++ndx)
775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Rel rel_mem;
777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Rel *rel = gelf_getrel (data, ndx, &rel_mem);
778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (rel == NULL)
7793614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	      error (2, 0, gettext ("cannot get relocation: %s"),
780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     elf_errmsg (-1));
781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((int) GELF_R_SYM (rel->r_info) == symndx
783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return true;
785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
786e16e14100fe2ff70535977fe9ebd32f8d7ca5146Mark Wielaard      else if (shdr->sh_entsize != 0)
787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	for (int ndx = 0; ndx < (int) (shdr->sh_size / shdr->sh_entsize);
788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     ++ndx)
789b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
790b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Rela rela_mem;
791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Rela *rela = gelf_getrela (data, ndx, &rela_mem);
792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (rela == NULL)
7933614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	      error (2, 0, gettext ("cannot get relocation: %s"),
794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     elf_errmsg (-1));
795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((int) GELF_R_SYM (rela->r_info) == symndx
797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return true;
799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return false;
803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
8064be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathstatic int
807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperregioncompare (const void *p1, const void *p2)
808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const struct region *r1 = (const struct region *) p1;
810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const struct region *r2 = (const struct region *) p2;
811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (r1->from < r2->from)
813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return -1;
814b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 1;
815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
8164be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8174be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8184be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathstatic int
8194be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathcompare_Elf32_Word (const void *p1, const void *p2)
8204be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath{
8214be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  const Elf32_Word *w1 = p1;
8224be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  const Elf32_Word *w2 = p2;
823274cbda6f5d5b7c57d488edaeb55876ba8705db3Mark Wielaard  return *w1 < *w2 ? -1 : *w1 > *w2 ? 1 : 0;
8244be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath}
8254be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8264be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathstatic int
8274be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathcompare_Elf64_Xword (const void *p1, const void *p2)
8284be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath{
8294be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  const Elf64_Xword *w1 = p1;
8304be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  const Elf64_Xword *w2 = p2;
8314be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  return *w1 < *w2 ? -1 : *w1 > *w2 ? 1 : 0;
8324be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath}
8334be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8344be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathstatic bool
8354be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathhash_content_equivalent (size_t entsize, Elf_Data *data1, Elf_Data *data2)
8364be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath{
8374be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath#define CHECK_HASH(Hash_Word)						      \
8384be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  {									      \
8394be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const hash1 = data1->d_buf;			      \
8404be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const hash2 = data2->d_buf;			      \
8414be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const size_t nbucket = hash1[0];					      \
8424be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const size_t nchain = hash1[1];					      \
8434be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    if (data1->d_size != (2 + nbucket + nchain) * sizeof hash1[0]	      \
8444be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	|| hash2[0] != nbucket || hash2[1] != nchain)			      \
8454be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      return false;							      \
8464be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8474be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const bucket1 = &hash1[2];				      \
8484be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const chain1 = &bucket1[nbucket];			      \
8494be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const bucket2 = &hash2[2];				      \
8504be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const chain2 = &bucket2[nbucket];			      \
8514be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8524be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    bool chain_ok[nchain];						      \
8534be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    Hash_Word temp1[nchain - 1];					      \
8544be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    Hash_Word temp2[nchain - 1];					      \
8554be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    memset (chain_ok, 0, sizeof chain_ok);				      \
8564be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    for (size_t i = 0; i < nbucket; ++i)				      \
8574be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      {									      \
8584be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	if (bucket1[i] >= nchain || bucket2[i] >= nchain)		      \
8594be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  return false;							      \
8604be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8614be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	size_t b1 = 0;							      \
8624be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	for (size_t p = bucket1[i]; p != STN_UNDEF; p = chain1[p])	      \
8634be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  if (p >= nchain || b1 >= nchain - 1)				      \
8644be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    return false;						      \
8654be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  else								      \
8664be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    temp1[b1++] = p;						      \
8674be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8684be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	size_t b2 = 0;							      \
8694be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	for (size_t p = bucket2[i]; p != STN_UNDEF; p = chain2[p])	      \
8704be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  if (p >= nchain || b2 >= nchain - 1)				      \
8714be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    return false;						      \
8724be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  else								      \
8734be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    temp2[b2++] = p;						      \
8744be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8754be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	if (b1 != b2)							      \
8764be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  return false;							      \
8774be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8784be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	qsort (temp1, b1, sizeof temp1[0], compare_##Hash_Word);	      \
8794be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	qsort (temp2, b2, sizeof temp2[0], compare_##Hash_Word);	      \
8804be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8814be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	for (b1 = 0; b1 < b2; ++b1)					      \
8824be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  if (temp1[b1] != temp2[b1])					      \
8834be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    return false;						      \
8844be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  else								      \
8854be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    chain_ok[temp1[b1]] = true;					      \
8864be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      }									      \
8874be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8884be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    for (size_t i = 0; i < nchain; ++i)					      \
8894be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      if (!chain_ok[i] && chain1[i] != chain2[i])			      \
8904be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	return false;							      \
8914be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8924be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    return true;							      \
8934be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  }
8944be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8954be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  switch (entsize)
8964be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    {
8974be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    case 4:
8984be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      CHECK_HASH (Elf32_Word);
8994be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      break;
9004be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    case 8:
9014be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      CHECK_HASH (Elf64_Xword);
9024be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      break;
9034be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    }
9044be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
9054be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  return false;
9064be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath}
9073cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
9083cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
9093cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper#include "debugpred.h"
910