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