1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Locate source files or functions which caused text relocations.
2712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard   Copyright (C) 2005-2010, 2012, 2014 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.
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
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>
28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <gelf.h>
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libdw.h>
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <libintl.h>
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <locale.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <search.h>
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdbool.h>
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdio.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h>
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <unistd.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
39fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich Drepper#include <system.h>
40fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich Drepper
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstruct segments
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Addr from;
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Addr to;
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Name and version of program.  */
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void print_version (FILE *stream, struct argp_state *state);
51fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Bug report address.  */
54fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich DrepperARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Values for the parameters which have no short form.  */
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define OPT_DEBUGINFO 0x100
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_("Input Selection:"), 0 },
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "root", 'r', "PATH", 0, N_("Prepend PATH to all file names"), 0 },
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { "debuginfo", OPT_DEBUGINFO, "PATH", 0,
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    N_("Use PATH as root of debuginfo hierarchy"), 0 },
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  { NULL, 0, NULL, 0, NULL, 0 }
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Short description of program.  */
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char doc[] = N_("\
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperLocate source of text relocations in FILEs (a.out by default).");
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Strings for arguments in help texts.  */
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char args_doc[] = N_("[FILE...]");
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Prototype for option handler.  */
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Data structure to communicate with argp functions.  */
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct argp argp =
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  options, parse_opt, args_doc, doc, NULL, NULL, NULL
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print symbols in file named FNAME.  */
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int process_file (const char *fname, bool more_than_one);
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Check for text relocations in the given file.  The segment
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   information is known.  */
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void check_rel (size_t nsegments, struct segments segments[nsegments],
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       GElf_Addr addr, Elf *elf, Elf_Scn *symscn, Dwarf *dw,
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       const char *fname, bool more_than_one,
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       void **knownsrcs);
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* User-provided root directory.  */
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *rootdir = "/";
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Root of debuginfo directory hierarchy.  */
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *debuginfo_root;
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppermain (int argc, char *argv[])
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int remaining;
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result = 0;
112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Set locale.  */
114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (void) setlocale (LC_ALL, "");
115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Make sure the message catalog can be found.  */
117b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Initialize the message catalog.  */
120b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  (void) textdomain (PACKAGE_TARNAME);
121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Parse and process arguments.  */
123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Tell the library which version we are expecting.  */
126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_version (EV_CURRENT);
127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If the user has not specified the root directory for the
129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     debuginfo hierarchy, we have to determine it ourselves.  */
130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (debuginfo_root == NULL)
131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      // XXX The runtime should provide this information.
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if defined __ia64__ || defined __alpha__
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debuginfo_root = "/usr/lib/debug";
135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#else
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debuginfo_root = (sizeof (long int) == 4
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			? "/usr/lib/debug" : "/usr/lib64/debug");
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (remaining == argc)
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    result = process_file ("a.out", false);
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Process all the remaining files.  */
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const bool more_than_one = remaining + 1 < argc;
147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      do
149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	result |= process_file (argv[remaining], more_than_one);
150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      while (++remaining < argc);
151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Print the version information.  */
158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
161b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper  fprintf (stream, "findtextrel (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("\
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperCopyright (C) %s Red Hat, Inc.\n\
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperThis is free software; see the source for copying conditions.  There is NO\n\
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
1663a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper"), "2012");
167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Handle program arguments.  */
172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic error_t
173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperparse_opt (int key, char *arg,
174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   struct argp_state *state __attribute__ ((unused)))
175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (key)
177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case 'r':
179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      rootdir = arg;
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case OPT_DEBUGINFO:
183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      debuginfo_root = arg;
184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ARGP_ERR_UNKNOWN;
188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppernoop (void *arg __attribute__ ((unused)))
195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperprocess_file (const char *fname, bool more_than_one)
201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int result = 0;
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  void *knownsrcs = NULL;
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t fname_len = strlen (fname);
206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t rootdir_len = strlen (rootdir);
207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  const char *real_fname = fname;
208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (fname[0] == '/' && (rootdir[0] != '/' || rootdir[1] != '\0'))
209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Prepend the user-provided root directory.  */
211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      char *new_fname = alloca (rootdir_len + fname_len + 2);
212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *((char *) mempcpy (stpcpy (mempcpy (new_fname, rootdir, rootdir_len),
213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				  "/"),
214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  fname, fname_len)) = '\0';
215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      real_fname = new_fname;
216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2183425454a10d307fae891fb667cf7969e945cde79Josh Stone  int fd = open (real_fname, O_RDONLY);
219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (fd == -1)
220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, errno, gettext ("cannot open '%s'"), fname);
222b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 1;
223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf == NULL)
227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("cannot create ELF descriptor for '%s': %s"),
229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     fname, elf_errmsg (-1));
230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      goto err_close;
231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Make sure the file is a DSO.  */
234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr ehdr_mem;
235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr == NULL)
237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("cannot get ELF header '%s': %s"),
239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     fname, elf_errmsg (-1));
240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    err_elf_close:
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf_end (elf);
242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    err_close:
243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      close (fd);
244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 1;
245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ehdr->e_type != ET_DYN)
248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      error (0, 0, gettext ("'%s' is not a DSO or PIE"), fname);
250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      goto err_elf_close;
251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Determine whether the DSO has text relocations at all and locate
254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     the symbol table.  */
255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *symscn = NULL;
256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Scn *scn = NULL;
25777221de070e8978c312d3e6b2c66a28dca4c37bcRoland McGrath  bool seen_dynamic = false;
25877221de070e8978c312d3e6b2c66a28dca4c37bcRoland McGrath  bool have_textrel = false;
25958af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath  while ((scn = elf_nextscn (elf, scn)) != NULL
26058af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath	 && (!seen_dynamic || symscn == NULL))
261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Handle the section if it is a symbol table.  */
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr shdr_mem;
264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (shdr == NULL)
267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0,
269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 gettext ("getting get section header of section %zu: %s"),
270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 elf_ndxscn (scn), elf_errmsg (-1));
271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto err_elf_close;
272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
27458af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath      switch (shdr->sh_type)
275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
27658af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath	case SHT_DYNAMIC:
27758af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath	  if (!seen_dynamic)
278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
27958af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath	      seen_dynamic = true;
28058af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath
28158af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath	      Elf_Data *data = elf_getdata (scn, NULL);
282b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
28358af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath	      for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize;
28458af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		   ++cnt)
285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
28658af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		  GElf_Dyn dynmem;
28758af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		  GElf_Dyn *dyn;
28858af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath
28958af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		  dyn = gelf_getdyn (data, cnt, &dynmem);
29058af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		  if (dyn == NULL)
29158af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		    {
29258af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		      error (0, 0, gettext ("cannot read dynamic section: %s"),
29358af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath			     elf_errmsg (-1));
29458af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		      goto err_elf_close;
29558af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		    }
29658af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath
29758af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		  if (dyn->d_tag == DT_TEXTREL
29858af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		      || (dyn->d_tag == DT_FLAGS
29958af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath			  && (dyn->d_un.d_val & DF_TEXTREL) != 0))
30058af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath		    have_textrel = true;
301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
30358af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath	  break;
30477221de070e8978c312d3e6b2c66a28dca4c37bcRoland McGrath
30558af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath	case SHT_SYMTAB:
30677221de070e8978c312d3e6b2c66a28dca4c37bcRoland McGrath	  symscn = scn;
30758af2001b92a8a8ee21a81b2845449ae8d038b7cRoland McGrath	  break;
30877221de070e8978c312d3e6b2c66a28dca4c37bcRoland McGrath	}
309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
31177221de070e8978c312d3e6b2c66a28dca4c37bcRoland McGrath  if (!have_textrel)
31277221de070e8978c312d3e6b2c66a28dca4c37bcRoland McGrath    {
31377221de070e8978c312d3e6b2c66a28dca4c37bcRoland McGrath      error (0, 0, gettext ("no text relocations reported in '%s'"), fname);
314a58951b183fb3e051870b19c95d8082a3efa3ddbMark Wielaard      goto err_elf_close;
31577221de070e8978c312d3e6b2c66a28dca4c37bcRoland McGrath    }
316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int fd2 = -1;
318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *elf2 = NULL;
319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Get the address ranges for the loaded segments.  */
320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t nsegments_max = 10;
321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t nsegments = 0;
322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct segments *segments
323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    = (struct segments *) malloc (nsegments_max * sizeof (segments[0]));
324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (segments == NULL)
325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    error (1, errno, gettext ("while reading ELF file"));
326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
327712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard  size_t phnum;
328712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard  if (elf_getphdrnum (elf, &phnum) != 0)
329712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard    error (1, 0, gettext ("cannot get program header count: %s"),
330712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard           elf_errmsg (-1));
331712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard
332712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard
333712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard  for (size_t i = 0; i < phnum; ++i)
334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr phdr_mem;
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr == NULL)
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  error (0, 0,
340712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard		 gettext ("cannot get program header index at offset %zd: %s"),
341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 i, elf_errmsg (-1));
342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  result = 1;
343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  goto next;
344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (nsegments == nsegments_max)
349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      nsegments_max *= 2;
351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      segments
352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		= (struct segments *) realloc (segments,
353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					       nsegments_max
354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					       * sizeof (segments[0]));
355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (segments == NULL)
356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  error (0, 0, gettext ("\
358712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaardcannot get program header index at offset %zd: %s"),
359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 i, elf_errmsg (-1));
360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  result = 1;
361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  goto next;
362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  segments[nsegments].from = phdr->p_vaddr;
366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  segments[nsegments].to = phdr->p_vaddr + phdr->p_memsz;
367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ++nsegments;
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (nsegments > 0)
372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Dwarf *dw = dwarf_begin_elf (elf, DWARF_C_READ, NULL);
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Look for debuginfo files if the information is not the in
376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 opened file itself.  This makes only sense if the input file
377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 is specified with an absolute path.  */
378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (dw == NULL && fname[0] == '/')
379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t debuginfo_rootlen = strlen (debuginfo_root);
381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  char *difname = (char *) alloca (rootdir_len + debuginfo_rootlen
382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					   + fname_len + 8);
383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  strcpy (mempcpy (stpcpy (mempcpy (mempcpy (difname, rootdir,
384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						     rootdir_len),
385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					    debuginfo_root,
386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					    debuginfo_rootlen),
387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   "/"),
388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   fname, fname_len),
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  ".debug");
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
3913425454a10d307fae891fb667cf7969e945cde79Josh Stone	  fd2 = open (difname, O_RDONLY);
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (fd2 != -1
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && (elf2 = elf_begin (fd2, ELF_C_READ_MMAP, NULL)) != NULL)
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    dw = dwarf_begin_elf (elf2, DWARF_C_READ, NULL);
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Look at all relocations and determine which modify
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 write-protected segments.  */
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      scn = NULL;
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      while ((scn = elf_nextscn (elf, scn)) != NULL)
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Handle the section if it is a symbol table.  */
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr shdr_mem;
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr == NULL)
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      error (0, 0,
4092ec957327cdfae6cee592a52958a9c937ea4b13cChih-Hung Hsieh		     gettext ("cannot get section header of section %zu: %s"),
410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     elf_ndxscn (scn), elf_errmsg (-1));
411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      result = 1;
412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      goto next;
413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && symscn == NULL)
417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      symscn = elf_getscn (elf, shdr->sh_link);
419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (symscn == NULL)
420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
421b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  error (0, 0, gettext ("\
422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot get symbol table section %zu in '%s': %s"),
423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 (size_t) shdr->sh_link, fname, elf_errmsg (-1));
424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  result = 1;
425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  goto next;
426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (shdr->sh_type == SHT_REL)
430b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
431b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      Elf_Data *data = elf_getdata (scn, NULL);
432b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
433b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      for (int cnt = 0;
434b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   (size_t) cnt < shdr->sh_size / shdr->sh_entsize;
435b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   ++cnt)
436b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Rel rel_mem;
438b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
439b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (rel == NULL)
440b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      error (0, 0, gettext ("\
442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot get relocation at index %d in section %zu in '%s': %s"),
443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, elf_ndxscn (scn), fname, elf_errmsg (-1));
444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      result = 1;
445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      goto next;
446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
447b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  check_rel (nsegments, segments, rel->r_offset, elf,
449b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     symscn, dw, fname, more_than_one, &knownsrcs);
450b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else if (shdr->sh_type == SHT_RELA)
453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      Elf_Data *data = elf_getdata (scn, NULL);
455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      for (int cnt = 0;
457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   (size_t) cnt < shdr->sh_size / shdr->sh_entsize;
458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		   ++cnt)
459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Rela rela_mem;
461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (rela == NULL)
463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      error (0, 0, gettext ("\
465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercannot get relocation at index %d in section %zu in '%s': %s"),
466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     cnt, elf_ndxscn (scn), fname, elf_errmsg (-1));
467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      result = 1;
468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      goto next;
469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  check_rel (nsegments, segments, rela->r_offset, elf,
472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			     symscn, dw, fname, more_than_one, &knownsrcs);
473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      dwarf_end (dw);
478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper next:
481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_end (elf);
482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_end (elf2);
483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  close (fd);
484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (fd2 != -1)
485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    close (fd2);
486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
487a1f359ed0d456fc85f14d54e87a21ac9c0c4e553Mark Wielaard  free (segments);
488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  tdestroy (knownsrcs, noop);
489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperptrcompare (const void *p1, const void *p2)
496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((uintptr_t) p1 < (uintptr_t) p2)
498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return -1;
499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if ((uintptr_t) p1 > (uintptr_t) p2)
500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return 1;
501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
504b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercheck_rel (size_t nsegments, struct segments segments[nsegments],
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   GElf_Addr addr, Elf *elf, Elf_Scn *symscn, Dwarf *dw,
508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   const char *fname, bool more_than_one, void **knownsrcs)
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (size_t cnt = 0; cnt < nsegments; ++cnt)
511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    if (segments[cnt].from <= addr && segments[cnt].to > addr)
512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      {
513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Dwarf_Die die_mem;
514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Dwarf_Die *die;
515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	Dwarf_Line *line;
516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	const char *src;
517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (more_than_one)
519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  printf ("%s: ", fname);
520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if ((die = dwarf_addrdie (dw, addr, &die_mem)) != NULL
522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    && (line = dwarf_getsrc_die (die, addr)) != NULL
523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    && (src = dwarf_linesrc (line, NULL, NULL)) != NULL)
524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* There can be more than one relocation against one file.
526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       Try to avoid multiple messages.  And yes, the code uses
527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       pointer comparison.  */
528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (tfind (src, knownsrcs, ptrcompare) == NULL)
529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		printf (gettext ("%s not compiled with -fpic/-fPIC\n"), src);
531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		tsearch (src, knownsrcs, ptrcompare);
532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    return;
534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	else
536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  {
537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* At least look at the symbol table to see which function
538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       the modified address is in.  */
539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    Elf_Data *symdata = elf_getdata (symscn, NULL);
540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Shdr shdr_mem;
541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    if (shdr != NULL)
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      {
544b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		GElf_Addr lowaddr = 0;
545b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		int lowidx = -1;
546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		GElf_Addr highaddr = ~0ul;
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		int highidx = -1;
548b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		GElf_Sym sym_mem;
549b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		GElf_Sym *sym;
550b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
551b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize;
552b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		     ++i)
553b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
554b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    sym = gelf_getsym (symdata, i, &sym_mem);
555b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sym == NULL)
556b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      continue;
557b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sym->st_value < addr && sym->st_value > lowaddr)
559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      {
560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			lowaddr = sym->st_value;
561b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			lowidx = i;
562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      }
563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sym->st_value > addr && sym->st_value < highaddr)
564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      {
565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			highaddr = sym->st_value;
566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			highidx = i;
567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      }
568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
570b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (lowidx != -1)
571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    sym = gelf_getsym (symdata, lowidx, &sym_mem);
573b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    assert (sym != NULL);
574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    const char *lowstr = elf_strptr (elf, shdr->sh_link,
576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						     sym->st_name);
577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    if (sym->st_value + sym->st_size > addr)
579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      {
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			/* It is this function.  */
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (tfind (lowstr, knownsrcs, ptrcompare) == NULL)
582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  {
583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    printf (gettext ("\
584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperthe file containing the function '%s' is not compiled with -fpic/-fPIC\n"),
585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				    lowstr);
586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    tsearch (lowstr, knownsrcs, ptrcompare);
587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  }
588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      }
589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else if (highidx == -1)
590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      printf (gettext ("\
591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperthe file containing the function '%s' might not be compiled with -fpic/-fPIC\n"),
592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      lowstr);
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    else
594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      {
595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			sym = gelf_getsym (symdata, highidx, &sym_mem);
596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			assert (sym != NULL);
597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			printf (gettext ("\
599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppereither the file containing the function '%s' or the file containing the function '%s' is not compiled with -fpic/-fPIC\n"),
600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				lowstr, elf_strptr (elf, shdr->sh_link,
601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						    sym->st_name));
602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      }
603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    return;
604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		else if (highidx != -1)
606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  {
607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    sym = gelf_getsym (symdata, highidx, &sym_mem);
608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    assert (sym != NULL);
609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    printf (gettext ("\
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperthe file containing the function '%s' might not be compiled with -fpic/-fPIC\n"),
612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			    elf_strptr (elf, shdr->sh_link, sym->st_name));
613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    return;
614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  }
615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      }
616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  }
617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	printf (gettext ("\
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppera relocation modifies memory at offset %llu in a write-protected segment\n"),
620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		(unsigned long long int) addr);
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	break;
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      }
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
6243cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
6253cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
6263cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper#include "debugpred.h"
627