elfcmp.c revision de2ed97f33139af5c7a0811e4ec66fc896a13cf2
1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Compare relevant content of two ELF files.
23a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper   Copyright (C) 2005-2012 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.  */
290e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper      if (unlikely (strcmp (sname1, sname2) != 0))
291b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
2924a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	  error (0, 0, gettext ("%s %s differ: section [%zu], [%zu] name"),
2934a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		 fname1, fname2, elf_ndxscn (scn1), elf_ndxscn (scn2));
2944a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	  DIFFERENCE;
295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
297b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We ignore certain sections.  */
298b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (strcmp (sname1, ".gnu_debuglink") == 0
299b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || strcmp (sname1, ".gnu.prelink_undo") == 0)
300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	continue;
301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr1->sh_type != shdr2->sh_type
303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  // XXX Any flags which should be ignored?
304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_flags != shdr2->sh_flags
305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_addr != shdr2->sh_addr
306059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  || (shdr1->sh_offset != shdr2->sh_offset
307059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      && (shdr1->sh_flags & SHF_ALLOC)
308059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	      && ehdr1->e_type != ET_REL)
309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_size != shdr2->sh_size
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_link != shdr2->sh_link
311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_info != shdr2->sh_info
312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_addralign != shdr2->sh_addralign
313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr1->sh_entsize != shdr2->sh_entsize)
3144a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	{
3154a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	  error (0, 0, gettext ("%s %s differ: section [%zu] '%s' header"),
3164a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		 fname1, fname2, elf_ndxscn (scn1), sname1);
3174a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	  DIFFERENCE;
3184a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	}
319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf_Data *data1 = elf_getdata (scn1, NULL);
321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data1 == NULL)
3223614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
323e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	       gettext ("cannot get content of section %zu in '%s': %s"),
324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_ndxscn (scn1), fname1, elf_errmsg (-1));
325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf_Data *data2 = elf_getdata (scn2, NULL);
327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data2 == NULL)
3283614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
329e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	       gettext ("cannot get content of section %zu in '%s': %s"),
330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_ndxscn (scn2), fname2, elf_errmsg (-1));
331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      switch (shdr1->sh_type)
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_DYNSYM:
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	case SHT_SYMTAB:
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Iterate over the symbol table.  We ignore the st_size
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     value of undefined symbols.  */
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (int ndx = 0; ndx < (int) (shdr1->sh_size / shdr1->sh_entsize);
339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ++ndx)
340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Sym sym1_mem;
342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Sym *sym1 = gelf_getsym (data1, ndx, &sym1_mem);
343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (sym1 == NULL)
3443614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath		error (2, 0,
345e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		       gettext ("cannot get symbol in '%s': %s"),
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       fname1, elf_errmsg (-1));
347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Sym sym2_mem;
348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      GElf_Sym *sym2 = gelf_getsym (data2, ndx, &sym2_mem);
349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (sym2 == NULL)
3503614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath		error (2, 0,
351e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		       gettext ("cannot get symbol in '%s': %s"),
352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       fname2, elf_errmsg (-1));
353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      const char *name1 = elf_strptr (elf1, shdr1->sh_link,
355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      sym1->st_name);
356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      const char *name2 = elf_strptr (elf2, shdr2->sh_link,
357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      sym2->st_name);
358e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	      if (unlikely (strcmp (name1, name2) != 0
359e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    || sym1->st_value != sym2->st_value
360e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    || (sym1->st_size != sym2->st_size
361e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper				&& sym1->st_shndx != SHN_UNDEF)
362e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    || sym1->st_info != sym2->st_info
363e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    || sym1->st_other != sym2->st_other
364e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    || sym1->st_shndx != sym1->st_shndx))
365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  // XXX Do we want to allow reordered symbol tables?
3677d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		symtab_mismatch:
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (! quiet)
3697d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		    {
3707d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		      if (elf_ndxscn (scn1) == elf_ndxscn (scn2))
3717d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			error (0, 0,
3727d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			       gettext ("%s %s differ: symbol table [%zu]"),
3737d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			       fname1, fname2, elf_ndxscn (scn1));
3747d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		      else
3757d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			error (0, 0, gettext ("\
3767d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper%s %s differ: symbol table [%zu,%zu]"),
3777d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			       fname1, fname2, elf_ndxscn (scn1),
3787d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			       elf_ndxscn (scn2));
3797d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		    }
3804a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		  DIFFERENCE;
3814a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		  break;
382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (sym1->st_shndx == SHN_UNDEF
385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && sym1->st_size != sym2->st_size)
386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* The size of the symbol in the object defining it
388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     might have changed.  That is OK unless the symbol
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     is used in a copy relocation.  Look over the
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     sections in both files and determine which
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     relocation section uses this symbol table
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     section.  Then look through the relocations to
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     see whether any copy relocation references this
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     symbol.  */
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (search_for_copy_reloc (ebl1, elf_ndxscn (scn1), ndx)
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      || search_for_copy_reloc (ebl2, elf_ndxscn (scn2), ndx))
3977d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		    goto symtab_mismatch;
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
4021fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	case SHT_NOTE:
4031fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	  /* Parse the note format and compare the notes themselves.  */
4041fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	  {
4051fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    GElf_Nhdr note1;
4061fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    GElf_Nhdr note2;
4071fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath
4081fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    size_t off1 = 0;
4091fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    size_t off2 = 0;
4101fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    size_t name_offset;
4111fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    size_t desc_offset;
4121fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    while (off1 < data1->d_size
4131fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		   && (off1 = gelf_getnote (data1, off1, &note1,
4141fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath					    &name_offset, &desc_offset)) > 0)
4151fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	      {
4161fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		const char *name1 = data1->d_buf + name_offset;
4171fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		const void *desc1 = data1->d_buf + desc_offset;
4181fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (off2 >= data2->d_size)
4191fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  {
4201fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    if (! quiet)
4211fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      error (0, 0, gettext ("\
4221fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: section [%zu] '%s' number of notes"),
4231fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			     fname1, fname2, elf_ndxscn (scn1), sname1);
4244a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		    DIFFERENCE;
4251fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  }
4261fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		off2 = gelf_getnote (data2, off2, &note2,
4271fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath				     &name_offset, &desc_offset);
4281fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (off2 == 0)
4291fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  error (2, 0, gettext ("\
4301fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrathcannot read note section [%zu] '%s' in '%s': %s"),
4311fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			 elf_ndxscn (scn2), sname2, fname2, elf_errmsg (-1));
4321fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		const char *name2 = data2->d_buf + name_offset;
4331fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		const void *desc2 = data2->d_buf + desc_offset;
4341fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath
4351fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (note1.n_namesz != note2.n_namesz
4361fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    || memcmp (name1, name2, note1.n_namesz))
4371fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  {
4381fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    if (! quiet)
4391fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      error (0, 0, gettext ("\
4401fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: section [%zu] '%s' note name"),
4411fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			     fname1, fname2, elf_ndxscn (scn1), sname1);
4424a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		    DIFFERENCE;
4431fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  }
4441fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (note1.n_type != note2.n_type)
4451fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  {
4461fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    if (! quiet)
4471fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      error (0, 0, gettext ("\
4481fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: section [%zu] '%s' note '%s' type"),
4491fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			     fname1, fname2, elf_ndxscn (scn1), sname1, name1);
4504a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		    DIFFERENCE;
4511fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  }
4521fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (note1.n_descsz != note2.n_descsz
4531fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    || memcmp (desc1, desc2, note1.n_descsz))
4541fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  {
4551fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    if (note1.n_type == NT_GNU_BUILD_ID
4561fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			&& note1.n_namesz == sizeof "GNU"
4571fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			&& !memcmp (name1, "GNU", sizeof "GNU"))
4581fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      {
4591fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			if (note1.n_descsz != note2.n_descsz)
4601fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			  {
4611fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			    if (! quiet)
4621fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			      error (0, 0, gettext ("\
4631fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: build ID length"),
4641fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath				     fname1, fname2);
4654a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath			    DIFFERENCE;
4661fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			  }
4671fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			else if (! ignore_build_id)
4681fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			  {
4691fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			    if (! quiet)
4701fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			      error (0, 0, gettext ("\
4711fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: build ID content"),
4721fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath				     fname1, fname2);
4734a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath			    DIFFERENCE;
4741fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			  }
4751fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      }
4761fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		    else
4771fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      {
4781fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			if (! quiet)
4791fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			  error (0, 0, gettext ("\
4801fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: section [%zu] '%s' note '%s' content"),
4811fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath				 fname1, fname2, elf_ndxscn (scn1), sname1,
4821fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath				 name1);
4834a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath			DIFFERENCE;
4841fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		      }
4851fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  }
4861fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	      }
4871fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	    if (off2 < data2->d_size)
4881fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	      {
4891fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		if (! quiet)
4901fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath		  error (0, 0, gettext ("\
4911fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath%s %s differ: section [%zu] '%s' number of notes"),
4921fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath			 fname1, fname2, elf_ndxscn (scn1), sname1);
4934a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		DIFFERENCE;
4941fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	      }
4951fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	  }
4961fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath	  break;
4971fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath
498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	default:
499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Compare the section content byte for byte.  */
500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  assert (shdr1->sh_type == SHT_NOBITS
501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || (data1->d_buf != NULL || data1->d_size == 0));
502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  assert (shdr2->sh_type == SHT_NOBITS
503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || (data2->d_buf != NULL || data1->d_size == 0));
504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
505e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	  if (unlikely (data1->d_size != data2->d_size
506e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			|| (shdr1->sh_type != SHT_NOBITS
507e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			    && memcmp (data1->d_buf, data2->d_buf,
508e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper				       data1->d_size) != 0)))
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
5104be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	      if (hash_inexact
5114be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath		  && shdr1->sh_type == SHT_HASH
5124be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath		  && data1->d_size == data2->d_size
5134be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath		  && hash_content_equivalent (shdr1->sh_entsize, data1, data2))
5144be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath		break;
5154be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (! quiet)
5177d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		{
5187d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		  if (elf_ndxscn (scn1) == elf_ndxscn (scn2))
5197d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		    error (0, 0, gettext ("\
5207d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper%s %s differ: section [%zu] '%s' content"),
5217d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			   fname1, fname2, elf_ndxscn (scn1), sname1);
5227d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		  else
5237d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		    error (0, 0, gettext ("\
5247d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper%s %s differ: section [%zu,%zu] '%s' content"),
5257d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			   fname1, fname2, elf_ndxscn (scn1),
5267d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper			   elf_ndxscn (scn2), sname1);
5277d48d6a13fa164209a5c75d27d10cf1cd7b1c4a9Ulrich Drepper		}
5284a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	      DIFFERENCE;
529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
534e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper  if (unlikely (scn1 != scn2))
535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (! quiet)
537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	error (0, 0,
538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       gettext ("%s %s differ: unequal amount of important sections"),
539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       fname1, fname2);
5404a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      DIFFERENCE;
541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We we look at gaps, create artificial ones for the parts of the
544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     program which we are not in sections.  */
545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct region ehdr_region;
546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct region phdr_region;
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (gaps != gaps_ignore)
548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ehdr_region.from = 0;
550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ehdr_region.to = ehdr1->e_ehsize;
551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ehdr_region.next = &phdr_region;
552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      phdr_region.from = ehdr1->e_phoff;
554bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath      phdr_region.to = ehdr1->e_phoff + phnum1 * ehdr1->e_phentsize;
555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      phdr_region.next = regions;
556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      regions = &ehdr_region;
558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      nregions += 2;
559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If we need to look at the gaps we need access to the file data.  */
562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *raw1 = NULL;
563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t size1 = 0;
564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *raw2 = NULL;
565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t size2 = 0;
566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct region *regionsarr = alloca (nregions * sizeof (struct region));
567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (gaps != gaps_ignore)
568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      raw1 = elf_rawfile (elf1, &size1);
570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (raw1 == NULL )
5713614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0, gettext ("cannot load data of '%s': %s"),
572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       fname1, elf_errmsg (-1));
573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      raw2 = elf_rawfile (elf2, &size2);
575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (raw2 == NULL )
5763614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0, gettext ("cannot load data of '%s': %s"),
577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       fname2, elf_errmsg (-1));
578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (size_t cnt = 0; cnt < nregions; ++cnt)
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  regionsarr[cnt] = *regions;
582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  regions = regions->next;
583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      qsort (regionsarr, nregions, sizeof (regionsarr[0]), regioncompare);
586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Compare the program header tables.  */
589bd733cae5159e3a3c4c05f7685559fa3ae8b58c6Roland McGrath  for (unsigned int ndx = 0; ndx < phnum1; ++ndx)
590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr phdr1_mem;
592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr *phdr1 = gelf_getphdr (elf1, ndx, &phdr1_mem);
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr1 == NULL)
5943614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
595e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	       gettext ("cannot get program header entry %d of '%s': %s"),
596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ndx, fname1, elf_errmsg (-1));
597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr phdr2_mem;
598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr *phdr2 = gelf_getphdr (elf2, ndx, &phdr2_mem);
599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ehdr2 == NULL)
6003614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
601e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	       gettext ("cannot get program header entry %d of '%s': %s"),
602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       ndx, fname2, elf_errmsg (-1));
603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
604e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper      if (unlikely (memcmp (phdr1, phdr2, sizeof (GElf_Phdr)) != 0))
605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (! quiet)
607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    error (0, 0, gettext ("%s %s differ: program header %d"),
608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   fname1, fname2, ndx);
6094a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath	  DIFFERENCE;
610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (gaps != gaps_ignore && phdr1->p_type == PT_LOAD)
613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t cnt = 0;
615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  while (cnt < nregions && regionsarr[cnt].to < phdr1->p_offset)
616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    ++cnt;
617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Off last = phdr1->p_offset;
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Off end = phdr1->p_offset + phdr1->p_filesz;
620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  while (cnt < nregions && regionsarr[cnt].from < end)
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (last < regionsarr[cnt].from)
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Compare the [LAST,FROM) region.  */
625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  assert (gaps == gaps_match);
626e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		  if (unlikely (memcmp (raw1 + last, raw2 + last,
627e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper					regionsarr[cnt].from - last) != 0))
628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    gapmismatch:
630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      if (!quiet)
631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			error (0, 0, gettext ("%s %s differ: gap"),
632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       fname1, fname2);
6334a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		      DIFFERENCE;
6344a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath		      break;
635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      last = regionsarr[cnt].to;
639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      ++cnt;
640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cnt == nregions && last < end)
643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    goto gapmismatch;
644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper out:
648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_end (elf1);
649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_end (elf2);
650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  close (fd1);
651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  close (fd2);
652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print the version information.  */
658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
661b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  fprintf (stream, "elfcmp (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("\
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperCopyright (C) %s Red Hat, Inc.\n\
664b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperThis is free software; see the source for copying conditions.  There is NO\n\
665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
6663a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper"), "2012");
667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle program arguments.  */
672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t
673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperparse_opt (int key, char *arg,
674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   struct argp_state *state __attribute__ ((unused)))
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (key)
677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'q':
679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      quiet = true;
680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6824a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath    case 'l':
6834a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      verbose = true;
6844a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath      break;
6854a14ef7b9a4b274fd45d17512cf0da42956b672bRoland McGrath
686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case OPT_GAPS:
687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (strcasecmp (arg, "ignore") == 0)
688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	gaps = gaps_ignore;
689e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper      else if (likely (strcasecmp (arg, "match") == 0))
690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	gaps = gaps_match;
691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  fprintf (stderr,
694e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		   gettext ("Invalid value '%s' for --gaps parameter."),
695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   arg);
696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  argp_help (&argp, stderr, ARGP_HELP_SEE,
697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     program_invocation_short_name);
698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  exit (1);
699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
7024be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    case OPT_HASH_INEXACT:
7034be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      hash_inexact = true;
7044be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      break;
7054be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
7061fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath    case OPT_IGNORE_BUILD_ID:
7071fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath      ignore_build_id = true;
7081fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath      break;
7091fb9c917a55fa30c5f6b27c30727a796f9b1e804Roland McGrath
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ARGP_ERR_UNKNOWN;
712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic Elf *
718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperopen_file (const char *fname, int *fdp, Ebl **eblp)
719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int fd = open (fname, O_RDONLY);
721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (unlikely (fd == -1))
7223614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath    error (2, errno, gettext ("cannot open '%s'"), fname);
723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf == NULL)
7253614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath    error (2, 0,
726e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	   gettext ("cannot create ELF descriptor for '%s': %s"),
727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   fname, elf_errmsg (-1));
728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Ebl *ebl = ebl_openbackend (elf);
729b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ebl == NULL)
7303614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath    error (2, 0,
731e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper	   gettext ("cannot create EBL descriptor for '%s'"), fname);
732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *fdp = fd;
734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *eblp = ebl;
735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return elf;
736b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic bool
740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppersearch_for_copy_reloc (Ebl *ebl, size_t scnndx, int symndx)
741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn = NULL;
743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr shdr_mem;
746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr == NULL)
7483614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       gettext ("cannot get section header of section %zu: %s"),
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_ndxscn (scn), elf_errmsg (-1));
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if ((shdr->sh_type != SHT_REL && shdr->sh_type != SHT_RELA)
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  || shdr->sh_link != scnndx)
754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	continue;
755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf_Data *data = elf_getdata (scn, NULL);
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (data == NULL)
7583614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	error (2, 0,
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       gettext ("cannot get content of section %zu: %s"),
760b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       elf_ndxscn (scn), elf_errmsg (-1));
761b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr->sh_type == SHT_REL)
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	for (int ndx = 0; ndx < (int) (shdr->sh_size / shdr->sh_entsize);
764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     ++ndx)
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Rel rel_mem;
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Rel *rel = gelf_getrel (data, ndx, &rel_mem);
768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (rel == NULL)
7693614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	      error (2, 0, gettext ("cannot get relocation: %s"),
770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     elf_errmsg (-1));
771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((int) GELF_R_SYM (rel->r_info) == symndx
773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return true;
775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	for (int ndx = 0; ndx < (int) (shdr->sh_size / shdr->sh_entsize);
778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     ++ndx)
779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Rela rela_mem;
781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Rela *rela = gelf_getrela (data, ndx, &rela_mem);
782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (rela == NULL)
7833614d99198838a888005e923b36e8e0fbd5ec432Roland McGrath	      error (2, 0, gettext ("cannot get relocation: %s"),
784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     elf_errmsg (-1));
785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if ((int) GELF_R_SYM (rela->r_info) == symndx
787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&& ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return true;
789b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
790b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return false;
793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
7964be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathstatic int
797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperregioncompare (const void *p1, const void *p2)
798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const struct region *r1 = (const struct region *) p1;
800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const struct region *r2 = (const struct region *) p2;
801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (r1->from < r2->from)
803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return -1;
804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 1;
805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
8064be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8074be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8084be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathstatic int
8094be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathcompare_Elf32_Word (const void *p1, const void *p2)
8104be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath{
8114be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  const Elf32_Word *w1 = p1;
8124be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  const Elf32_Word *w2 = p2;
8134be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  assert (sizeof (int) >= sizeof (*w1));
8144be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  return (int) *w1 - (int) *w2;
8154be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath}
8164be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8174be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathstatic int
8184be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathcompare_Elf64_Xword (const void *p1, const void *p2)
8194be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath{
8204be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  const Elf64_Xword *w1 = p1;
8214be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  const Elf64_Xword *w2 = p2;
8224be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  return *w1 < *w2 ? -1 : *w1 > *w2 ? 1 : 0;
8234be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath}
8244be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8254be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathstatic bool
8264be1524398af8e24011cfdfa77c66832f8654a56Roland McGrathhash_content_equivalent (size_t entsize, Elf_Data *data1, Elf_Data *data2)
8274be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath{
8284be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath#define CHECK_HASH(Hash_Word)						      \
8294be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  {									      \
8304be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const hash1 = data1->d_buf;			      \
8314be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const hash2 = data2->d_buf;			      \
8324be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const size_t nbucket = hash1[0];					      \
8334be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const size_t nchain = hash1[1];					      \
8344be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    if (data1->d_size != (2 + nbucket + nchain) * sizeof hash1[0]	      \
8354be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	|| hash2[0] != nbucket || hash2[1] != nchain)			      \
8364be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      return false;							      \
8374be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8384be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const bucket1 = &hash1[2];				      \
8394be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const chain1 = &bucket1[nbucket];			      \
8404be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const bucket2 = &hash2[2];				      \
8414be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    const Hash_Word *const chain2 = &bucket2[nbucket];			      \
8424be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8434be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    bool chain_ok[nchain];						      \
8444be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    Hash_Word temp1[nchain - 1];					      \
8454be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    Hash_Word temp2[nchain - 1];					      \
8464be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    memset (chain_ok, 0, sizeof chain_ok);				      \
8474be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    for (size_t i = 0; i < nbucket; ++i)				      \
8484be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      {									      \
8494be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	if (bucket1[i] >= nchain || bucket2[i] >= nchain)		      \
8504be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  return false;							      \
8514be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8524be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	size_t b1 = 0;							      \
8534be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	for (size_t p = bucket1[i]; p != STN_UNDEF; p = chain1[p])	      \
8544be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  if (p >= nchain || b1 >= nchain - 1)				      \
8554be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    return false;						      \
8564be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  else								      \
8574be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    temp1[b1++] = p;						      \
8584be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8594be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	size_t b2 = 0;							      \
8604be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	for (size_t p = bucket2[i]; p != STN_UNDEF; p = chain2[p])	      \
8614be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  if (p >= nchain || b2 >= nchain - 1)				      \
8624be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    return false;						      \
8634be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  else								      \
8644be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    temp2[b2++] = p;						      \
8654be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8664be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	if (b1 != b2)							      \
8674be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  return false;							      \
8684be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8694be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	qsort (temp1, b1, sizeof temp1[0], compare_##Hash_Word);	      \
8704be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	qsort (temp2, b2, sizeof temp2[0], compare_##Hash_Word);	      \
8714be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8724be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	for (b1 = 0; b1 < b2; ++b1)					      \
8734be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  if (temp1[b1] != temp2[b1])					      \
8744be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    return false;						      \
8754be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	  else								      \
8764be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	    chain_ok[temp1[b1]] = true;					      \
8774be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      }									      \
8784be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8794be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    for (size_t i = 0; i < nchain; ++i)					      \
8804be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      if (!chain_ok[i] && chain1[i] != chain2[i])			      \
8814be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	return false;							      \
8824be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath									      \
8834be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    return true;							      \
8844be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  }
8854be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8864be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  switch (entsize)
8874be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    {
8884be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    case 4:
8894be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      CHECK_HASH (Elf32_Word);
8904be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      break;
8914be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    case 8:
8924be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      CHECK_HASH (Elf64_Xword);
8934be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath      break;
8944be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath    }
8954be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath
8964be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath  return false;
8974be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath}
8983cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
8993cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
9003cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper#include "debugpred.h"
901