125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the strings of printable characters in files.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 2005-2010, 2012 Red Hat, Inc.
325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   This file is part of Red Hat elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   it under the terms of the GNU General Public License as published by the
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Free Software Foundation; version 2 of the License.
925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   You should have received a copy of the GNU General Public License along
1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is an included package of the Open Invention Network.
2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   An included package of the Open Invention Network is a package for which
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Open Invention Network licensees cross-license their patents.  No patent
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   license is granted, either expressly or impliedly, by designation as an
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   included package.  Should you wish to participate in the Open Invention
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Network licensing program, please visit www.openinventionnetwork.com
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   <http://www.openinventionnetwork.com>.  */
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <argp.h>
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <ctype.h>
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <endian.h>
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <errno.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <error.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h>
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <inttypes.h>
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libintl.h>
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <locale.h>
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h>
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio.h>
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio_ext.h>
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h>
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h>
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h>
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/mman.h>
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h>
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/stat.h>
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h>
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Prototypes of local functions.  */
5625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int read_fd (int fd, const char *fname, off64_t fdlen);
5725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int read_elf (Elf *elf, int fd, const char *fname, off64_t fdlen);
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Name and version of program.  */
6125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_version (FILE *stream, struct argp_state *state);
6225b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Bug report address.  */
6525b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Definitions of arguments for argp functions.  */
6825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct argp_option options[] =
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Output Selection:"), 0 },
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "all", 'a', NULL, 0, N_("Scan entire file, not only loaded sections"), 0 },
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "bytes", 'n', "MIN-LEN", 0,
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Only NUL-terminated sequences of MIN-LEN characters or more are printed"), 0 },
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "encoding", 'e', "SELECTOR", 0, N_("\
7525b3c049e70834cf33790a28643ab058b507b35cBen ChengSelect character size and endianess: s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit"),
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    0},
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "print-file-name", 'f', NULL, 0,
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Print name of the file before each string."), 0 },
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { "radix", 't', "{o,d,x}", 0,
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Print location of the string in base 8, 10, or 16 respectively."), 0 },
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'o', NULL, 0, N_("Alias for --radix=o"), 0 },
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, NULL, 0 }
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Short description of program.  */
8825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char doc[] = N_("\
8925b3c049e70834cf33790a28643ab058b507b35cBen ChengPrint the strings of printable characters in files.");
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Strings for arguments in help texts.  */
9225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char args_doc[] = N_("[FILE...]");
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Prototype for option handler.  */
9525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Data structure to communicate with argp functions.  */
9825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct argp argp =
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  options, parse_opt, args_doc, doc, NULL, NULL, NULL
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Global variables.  */
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if whole file and not only loaded sections are looked at.  */
10725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool entire_file;
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Minimum length of any sequence reported.  */
11025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t min_len = 4;
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Number of bytes per character.  */
11325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t bytes_per_char = 1;
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Minimum length of any sequence reported in bytes.  */
11625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t min_len_bytes;
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if multibyte characters are in big-endian order.  */
11925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool big_endian;
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True unless 7-bit ASCII are expected.  */
12225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool char_7bit;
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* True if file names should be printed before strings.  */
12525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool print_file_name;
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Location print format string.  */
12825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *locfmt;
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Page size in use.  */
13125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t ps;
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Mapped parts of the ELF file.  */
13525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned char *elfmap;
13625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic unsigned char *elfmap_base;
13725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t elfmap_size;
13825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic off64_t elfmap_off;
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14125b3c049e70834cf33790a28643ab058b507b35cBen Chengint
14225b3c049e70834cf33790a28643ab058b507b35cBen Chengmain (int argc, char *argv[])
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We use no threads.  */
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set locale.  */
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) setlocale (LC_ALL, "");
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make sure the message catalog can be found.  */
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Initialize the message catalog.  */
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) textdomain (PACKAGE_TARNAME);
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Parse and process arguments.  */
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int remaining;
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Tell the library which version we are expecting.  */
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf_version (EV_CURRENT);
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Determine the page size.  We will likely need it a couple of times.  */
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ps = sysconf (_SC_PAGESIZE);
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct stat64 st;
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = 0;
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (remaining == argc)
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* We read from standard input.  This we cannot do for a
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng       structured file.  */
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    result = read_fd (STDIN_FILENO,
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      print_file_name ? "{standard input}" : NULL,
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      (fstat64 (STDIN_FILENO, &st) == 0 && S_ISREG (st.st_mode))
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      ? st.st_size : INT64_C (0x7fffffffffffffff));
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    do
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	int fd = (strcmp (argv[remaining], "-") == 0
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ? STDIN_FILENO : open (argv[remaining], O_RDONLY));
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (unlikely (fd == -1))
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (0, errno, gettext ("cannot open '%s'"), argv[remaining]);
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    result = 1;
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	else
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    const char *fname = print_file_name ? argv[remaining] : NULL;
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    int fstat_fail = fstat64 (fd, &st);
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    off64_t fdlen = (fstat_fail
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     ? INT64_C (0x7fffffffffffffff) : st.st_size);
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (fdlen > (off64_t) min_len_bytes)
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		Elf *elf = NULL;
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (entire_file
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    || fstat_fail
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    || !S_ISREG (st.st_mode)
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    || (elf = elf_begin (fd, ELF_C_READ, NULL)) == NULL
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    || elf_kind (elf) != ELF_K_ELF)
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  result |= read_fd (fd, fname, fdlen);
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		else
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  result |= read_elf (elf, fd, fname, fdlen);
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* This call will succeed even if ELF is NULL.  */
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		elf_end (elf);
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (strcmp (argv[remaining], "-") != 0)
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      close (fd);
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (elfmap != NULL && elfmap != MAP_FAILED)
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  munmap (elfmap, elfmap_size);
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	elfmap = NULL;
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    while (++remaining < argc);
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the version information.  */
22325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
22425b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, "strings (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, gettext ("\
22825b3c049e70834cf33790a28643ab058b507b35cBen ChengCopyright (C) %s Red Hat, Inc.\n\
22925b3c049e70834cf33790a28643ab058b507b35cBen ChengThis is free software; see the source for copying conditions.  There is NO\n\
23025b3c049e70834cf33790a28643ab058b507b35cBen Chengwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng"), "2012");
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle program arguments.  */
23725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t
23825b3c049e70834cf33790a28643ab058b507b35cBen Chengparse_opt (int key, char *arg,
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   struct argp_state *state __attribute__ ((unused)))
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (key)
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'a':
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      entire_file = true;
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'e':
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We expect a string of one character.  */
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (arg[1] != '\0' ? '\0' : arg[0])
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 's':
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'S':
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char_7bit = arg[0] == 's';
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bytes_per_char = 1;
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'b':
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'B':
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  big_endian = true;
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* FALLTHROUGH */
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'l':
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'L':
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bytes_per_char = isupper (arg[0]) ? 4 : 2;
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0, gettext ("invalid value '%s' for %s parameter"),
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 arg, "-e");
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE, "strings");
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return ARGP_ERR_UNKNOWN;
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'f':
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      print_file_name = true;
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'n':
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      min_len = atoi (arg);
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'o':
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto octfmt;
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 't':
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (arg[0])
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'd':
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  locfmt = "%7" PRId64 " ";
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'o':
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	octfmt:
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  locfmt = "%7" PRIo64 " ";
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'x':
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  locfmt = "%7" PRIx64 " ";
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	default:
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0, gettext ("invalid value '%s' for %s parameter"),
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 arg, "-t");
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE, "strings");
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return ARGP_ERR_UNKNOWN;
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ARGP_KEY_FINI:
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Compute the length in bytes of any match.  */
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (min_len <= 0 || min_len > INT_MAX / bytes_per_char)
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0,
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       gettext ("invalid minimum length of matched string size"));
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      min_len_bytes = min_len * bytes_per_char;
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return ARGP_ERR_UNKNOWN;
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
32625b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_chunk_mb (const char *fname, const unsigned char *buf, off64_t to,
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  size_t len, char **unprinted)
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t curlen = *unprinted == NULL ? 0 : strlen (*unprinted);
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *start = buf;
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (len >= bytes_per_char)
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint32_t ch;
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (bytes_per_char == 2)
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (big_endian)
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ch = buf[0] << 8 | buf[1];
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ch = buf[1] << 8 | buf[0];
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (big_endian)
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ch = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    ch = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ch <= 255 && (isprint (ch) || ch == '\t'))
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++buf;
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++curlen;
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (curlen >= min_len)
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* We found a match.  */
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (fname != NULL))
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked (fname, stdout);
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked (": ", stdout);
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (locfmt != NULL))
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf (locfmt, (int64_t) to - len - (buf - start));
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (*unprinted != NULL))
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked (*unprinted, stdout);
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  free (*unprinted);
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *unprinted = NULL;
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* There is no sane way of printing the string.  If we
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 assume the file data is encoded in UCS-2/UTF-16 or
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 UCS-4/UTF-32 respectively we could covert the string.
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 But there is no such guarantee.  */
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      fwrite_unlocked (start, 1, buf - start, stdout);
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      putc_unlocked ('\n', stdout);
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = ++buf;
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  curlen =  0;
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (len <= min_len)
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      --len;
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (curlen != 0)
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *unprinted = xstrndup ((const char *) start, curlen);
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
40025b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_chunk (const char *fname, const unsigned char *buf, off64_t to,
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       size_t len, char **unprinted)
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We are not going to slow the check down for the 2- and 4-byte
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     encodings.  Handle them special.  */
40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (bytes_per_char != 1))
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      process_chunk_mb (fname, buf, to, len, unprinted);
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return;
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t curlen = *unprinted == NULL ? 0 : strlen (*unprinted);
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const unsigned char *start = buf;
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (len > 0)
41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((isprint (*buf) || *buf == '\t') && (! char_7bit || *buf <= 127))
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++buf;
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++curlen;
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (curlen >= min_len)
42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* We found a match.  */
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (likely (fname != NULL))
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked (fname, stdout);
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked (": ", stdout);
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (likely (locfmt != NULL))
43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf (locfmt, (int64_t) to - len - (buf - start));
43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (*unprinted != NULL))
43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fputs_unlocked (*unprinted, stdout);
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  free (*unprinted);
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *unprinted = NULL;
43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      fwrite_unlocked (start, 1, buf - start, stdout);
44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      putc_unlocked ('\n', stdout);
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  start = ++buf;
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  curlen =  0;
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (len <= min_len)
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      --len;
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (curlen != 0)
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *unprinted = xstrndup ((const char *) start, curlen);
45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Map a file in as large chunks as possible.  */
46025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void *
46125b3c049e70834cf33790a28643ab058b507b35cBen Chengmap_file (int fd, off64_t start_off, off64_t fdlen, size_t *map_sizep)
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if _MUDFLAP
46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) fd;
46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) start_off;
46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) fdlen;
46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) map_sizep;
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return MAP_FAILED;
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Maximum size we mmap.  We use an #ifdef to avoid overflows on
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     32-bit machines.  64-bit machines these days do not have usable
47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     address spaces larger than about 43 bits.  Not that any file
47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     should be that large.  */
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng# if SIZE_MAX > 0xffffffff
47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const size_t mmap_max = 0x4000000000lu;
47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng# else
47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const size_t mmap_max = 0x40000000lu;
47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# endif
47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Try to mmap the file.  */
48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t map_size = MIN ((off64_t) mmap_max, fdlen);
48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const size_t map_size_min = MAX (MAX (SIZE_MAX / 16, 2 * ps),
48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   roundup (2 * min_len_bytes + 1, ps));
48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  void *mem;
48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (1)
48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We map the memory for reading only here.  Since we will
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 always look at every byte of the file it makes sense to
48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 use MAP_POPULATE.  */
49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      mem = mmap64 (NULL, map_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE,
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    fd, start_off);
49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (mem != MAP_FAILED)
49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We will go through the mapping sequentially.  */
49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (void) posix_madvise (mem, map_size, POSIX_MADV_SEQUENTIAL);
49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (errno != EINVAL && errno != ENOMEM)
49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* This is an error other than the lack of address space.  */
50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Maybe the size of the mapping is too big.  Try again.  */
50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      map_size /= 2;
50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (map_size < map_size_min)
50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* That size should have fit.  */
50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *map_sizep = map_size;
51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return mem;
51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Read the file without mapping.  */
51625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
51725b3c049e70834cf33790a28643ab058b507b35cBen Chengread_block_no_mmap (int fd, const char *fname, off64_t from, off64_t fdlen)
51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *unprinted = NULL;
52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define CHUNKSIZE 65536
52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *buf = xmalloc (CHUNKSIZE + min_len_bytes
52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				+ bytes_per_char - 1);
52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t ntrailer = 0;
52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = 0;
52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (fdlen > 0)
52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + ntrailer,
52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng					    MIN (fdlen, CHUNKSIZE)));
52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (n == 0)
53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* There are less than MIN_LEN+1 bytes left so there cannot be
53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     another match.  */
53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (unprinted == NULL || ntrailer == 0);
53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (n < 0))
53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Something went wrong.  */
53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  result = 1;
54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Account for the number of bytes read in this round.  */
54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fdlen -= n;
54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Do not use the signed N value.  Note that the addition cannot
54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 overflow.  */
54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t nb = (size_t) n + ntrailer;
54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (nb >= min_len_bytes)
55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We only use complete characters.  */
55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  nb &= ~(bytes_per_char - 1);
55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  process_chunk (fname, buf, from + nb, nb, &unprinted);
55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* If the last bytes of the buffer (modulo the character
55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     size) have been printed we are not copying them.  */
55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t to_keep = unprinted != NULL ? 0 : min_len_bytes;
55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  memmove (buf, buf + nb - to_keep, to_keep);
56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ntrailer = to_keep;
56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  from += nb;
56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	ntrailer = nb;
56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (buf);
56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Don't print anything we collected so far.  There is no
57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     terminating NUL byte.  */
57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (unprinted);
57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
57925b3c049e70834cf33790a28643ab058b507b35cBen Chengread_block (int fd, const char *fname, off64_t fdlen, off64_t from, off64_t to)
58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elfmap == NULL)
58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We need a completely new mapping.  */
58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elfmap_off = from & ~(ps - 1);
58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elfmap_base = elfmap = map_file (fd, elfmap_off, fdlen, &elfmap_size);
58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (elfmap == MAP_FAILED))
58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Let the kernel know we are going to read everything in sequence.  */
58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	(void) posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elfmap == MAP_FAILED))
59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Read from the file descriptor.  For this we must position the
59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 read pointer.  */
59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      // XXX Eventually add flag which avoids this if the position
59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      // XXX is known to match.
59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (from != 0 && lseek64 (fd, from, SEEK_SET) != from)
59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, errno, gettext ("lseek64 failed"));
60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return read_block_no_mmap (fd, fname, from, to - from);
60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert ((off64_t) min_len_bytes < fdlen);
60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (to < (off64_t) elfmap_off || from > (off64_t) (elfmap_off + elfmap_size))
60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* The existing mapping cannot fit at all.  Map the new area.
60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 We always map the full range of ELFMAP_SIZE bytes even if
61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 this extend beyond the end of the file.  The Linux kernel
61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 handles this OK if the access pages are not touched.  */
61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elfmap_off = from & ~(ps - 1);
61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (mmap64 (elfmap, elfmap_size, PROT_READ,
61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  MAP_PRIVATE | MAP_POPULATE | MAP_FIXED, fd, from)
61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  == MAP_FAILED)
61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, errno, gettext ("re-mmap failed"));
61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elfmap_base = elfmap;
61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *unprinted = NULL;
62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Use the existing mapping as much as possible.  If necessary, map
62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     new pages.  */
62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (from >= (off64_t) elfmap_off
62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      && from < (off64_t) (elfmap_off + elfmap_size))
62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* There are at least a few bytes in this mapping which we can
62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng       use.  */
62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    process_chunk (fname, elfmap_base + (from - elfmap_off),
62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   MIN (to, (off64_t) (elfmap_off + elfmap_size)),
63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   MIN (to, (off64_t) (elfmap_off + elfmap_size)) - from,
63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   &unprinted);
63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (to > (off64_t) (elfmap_off + elfmap_size))
63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unsigned char *remap_base = elfmap_base;
63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t read_now = elfmap_size - (elfmap_base - elfmap);
63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (from >= (off64_t) elfmap_off
63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && from < (off64_t) (elfmap_off + elfmap_size));
64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      off64_t handled_to = elfmap_off + elfmap_size;
64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (elfmap == elfmap_base
64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || (elfmap_base - elfmap
64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  == (ptrdiff_t) ((min_len_bytes + ps - 1) & ~(ps - 1))));
64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elfmap == elfmap_base)
64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t keep_area = (min_len_bytes + ps - 1) & ~(ps - 1);
64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (elfmap_size >= keep_area + ps);
64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* The keep area is used for the content of the previous
64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     buffer we have to keep.  This means copying those bytes
65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     and for this we have to make the data writable.  */
65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (mprotect (elfmap, keep_area, PROT_READ | PROT_WRITE)
65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			!= 0))
65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, errno, gettext ("mprotect failed"));
65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elfmap_base = elfmap + keep_area;
65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (1)
65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Map the rest of the file, eventually again in pieces.
66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     We speed things up with a nice Linux feature.  Note
66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     that we have at least two pages mapped.  */
66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t to_keep = unprinted != NULL ? 0 : min_len_bytes;
66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (read_now >= to_keep);
66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  memmove (elfmap_base - to_keep,
66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   remap_base + read_now - to_keep, to_keep);
66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  remap_base = elfmap_base;
66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert ((elfmap_size - (elfmap_base - elfmap)) % bytes_per_char
67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  == 0);
67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  read_now = MIN (to - handled_to,
67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (ptrdiff_t) elfmap_size - (elfmap_base - elfmap));
67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (handled_to % ps == 0);
67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (handled_to % bytes_per_char == 0);
67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (mmap64 (remap_base, read_now, PROT_READ,
67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      MAP_PRIVATE | MAP_POPULATE | MAP_FIXED, fd, handled_to)
67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      == MAP_FAILED)
68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, errno, gettext ("re-mmap failed"));
68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elfmap_off = handled_to;
68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  process_chunk (fname, remap_base - to_keep,
68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 elfmap_off + (read_now & ~(bytes_per_char - 1)),
68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 to_keep + (read_now & ~(bytes_per_char - 1)),
68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 &unprinted);
68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  handled_to += read_now;
68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (handled_to >= to)
68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Don't print anything we collected so far.  There is no
69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     terminating NUL byte.  */
69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (unprinted);
69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
70125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
70225b3c049e70834cf33790a28643ab058b507b35cBen Chengread_fd (int fd, const char *fname, off64_t fdlen)
70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return read_block (fd, fname, fdlen, 0, fdlen);
70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
70825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
70925b3c049e70834cf33790a28643ab058b507b35cBen Chengread_elf (Elf *elf, int fd, const char *fname, off64_t fdlen)
71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (fdlen >= 0);
71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We will look at each section separately.  The ELF file is not
71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     mmapped.  The libelf implementation will load the needed parts on
71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     demand.  Since we only interate over the section header table the
71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     memory consumption at this stage is kept minimal.  */
71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = elf_nextscn (elf, NULL);
71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (scn == NULL)
71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return read_fd (fd, fname, fdlen);
72025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = 0;
72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Only look in sections which are loaded at runtime and
72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 actually have content.  */
72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr != NULL && shdr->sh_type != SHT_NOBITS
73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && (shdr->sh_flags & SHF_ALLOC) != 0)
73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result |= read_block (fd, fname, fdlen, shdr->sh_offset,
73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      shdr->sh_offset + shdr->sh_size);
73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (elf, scn)) != NULL);
73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elfmap != NULL && elfmap != MAP_FAILED)
73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    munmap (elfmap, elfmap_size);
73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elfmap = NULL;
73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "debugpred.h"
745