Home | History | Annotate | Download | only in src
      1 /* Print the strings of printable characters in files.
      2    Copyright (C) 2005-2010, 2012 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 2005.
      5 
      6    Red Hat elfutils is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by the
      8    Free Software Foundation; version 2 of the License.
      9 
     10    Red Hat elfutils is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13    General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License along
     16    with Red Hat elfutils; if not, write to the Free Software Foundation,
     17    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     18 
     19    Red Hat elfutils is an included package of the Open Invention Network.
     20    An included package of the Open Invention Network is a package for which
     21    Open Invention Network licensees cross-license their patents.  No patent
     22    license is granted, either expressly or impliedly, by designation as an
     23    included package.  Should you wish to participate in the Open Invention
     24    Network licensing program, please visit www.openinventionnetwork.com
     25    <http://www.openinventionnetwork.com>.  */
     26 
     27 #ifdef HAVE_CONFIG_H
     28 # include <config.h>
     29 #endif
     30 
     31 #include <argp.h>
     32 #include <assert.h>
     33 #include <ctype.h>
     34 #include <endian.h>
     35 #include <errno.h>
     36 #include <error.h>
     37 #include <fcntl.h>
     38 #include <gelf.h>
     39 #include <inttypes.h>
     40 #include <libintl.h>
     41 #include <locale.h>
     42 #include <stdbool.h>
     43 #include <stdio.h>
     44 #include <stdio_ext.h>
     45 #include <stdlib.h>
     46 #include <string.h>
     47 #include <unistd.h>
     48 #include <sys/mman.h>
     49 #include <sys/param.h>
     50 #include <sys/stat.h>
     51 
     52 #include <system.h>
     53 
     54 
     55 /* Prototypes of local functions.  */
     56 static int read_fd (int fd, const char *fname, off64_t fdlen);
     57 static int read_elf (Elf *elf, int fd, const char *fname, off64_t fdlen);
     58 
     59 
     60 /* Name and version of program.  */
     61 static void print_version (FILE *stream, struct argp_state *state);
     62 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
     63 
     64 /* Bug report address.  */
     65 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
     66 
     67 /* Definitions of arguments for argp functions.  */
     68 static const struct argp_option options[] =
     69 {
     70   { NULL, 0, NULL, 0, N_("Output Selection:"), 0 },
     71   { "all", 'a', NULL, 0, N_("Scan entire file, not only loaded sections"), 0 },
     72   { "bytes", 'n', "MIN-LEN", 0,
     73     N_("Only NUL-terminated sequences of MIN-LEN characters or more are printed"), 0 },
     74   { "encoding", 'e', "SELECTOR", 0, N_("\
     75 Select character size and endianess: s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit"),
     76     0},
     77   { "print-file-name", 'f', NULL, 0,
     78     N_("Print name of the file before each string."), 0 },
     79   { "radix", 't', "{o,d,x}", 0,
     80     N_("Print location of the string in base 8, 10, or 16 respectively."), 0 },
     81   { NULL, 'o', NULL, 0, N_("Alias for --radix=o"), 0 },
     82 
     83   { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
     84   { NULL, 0, NULL, 0, NULL, 0 }
     85 };
     86 
     87 /* Short description of program.  */
     88 static const char doc[] = N_("\
     89 Print the strings of printable characters in files.");
     90 
     91 /* Strings for arguments in help texts.  */
     92 static const char args_doc[] = N_("[FILE...]");
     93 
     94 /* Prototype for option handler.  */
     95 static error_t parse_opt (int key, char *arg, struct argp_state *state);
     96 
     97 /* Data structure to communicate with argp functions.  */
     98 static struct argp argp =
     99 {
    100   options, parse_opt, args_doc, doc, NULL, NULL, NULL
    101 };
    102 
    103 
    104 /* Global variables.  */
    105 
    106 /* True if whole file and not only loaded sections are looked at.  */
    107 static bool entire_file;
    108 
    109 /* Minimum length of any sequence reported.  */
    110 static size_t min_len = 4;
    111 
    112 /* Number of bytes per character.  */
    113 static size_t bytes_per_char = 1;
    114 
    115 /* Minimum length of any sequence reported in bytes.  */
    116 static size_t min_len_bytes;
    117 
    118 /* True if multibyte characters are in big-endian order.  */
    119 static bool big_endian;
    120 
    121 /* True unless 7-bit ASCII are expected.  */
    122 static bool char_7bit;
    123 
    124 /* True if file names should be printed before strings.  */
    125 static bool print_file_name;
    126 
    127 /* Location print format string.  */
    128 static const char *locfmt;
    129 
    130 /* Page size in use.  */
    131 static size_t ps;
    132 
    133 
    134 /* Mapped parts of the ELF file.  */
    135 static unsigned char *elfmap;
    136 static unsigned char *elfmap_base;
    137 static size_t elfmap_size;
    138 static off64_t elfmap_off;
    139 
    140 
    141 int
    142 main (int argc, char *argv[])
    143 {
    144   /* We use no threads.  */
    145   __fsetlocking (stdin, FSETLOCKING_BYCALLER);
    146   __fsetlocking (stdout, FSETLOCKING_BYCALLER);
    147 
    148   /* Set locale.  */
    149   (void) setlocale (LC_ALL, "");
    150 
    151   /* Make sure the message catalog can be found.  */
    152   (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
    153 
    154   /* Initialize the message catalog.  */
    155   (void) textdomain (PACKAGE_TARNAME);
    156 
    157   /* Parse and process arguments.  */
    158   int remaining;
    159   (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
    160 
    161   /* Tell the library which version we are expecting.  */
    162   elf_version (EV_CURRENT);
    163 
    164   /* Determine the page size.  We will likely need it a couple of times.  */
    165   ps = sysconf (_SC_PAGESIZE);
    166 
    167   struct stat64 st;
    168   int result = 0;
    169   if (remaining == argc)
    170     /* We read from standard input.  This we cannot do for a
    171        structured file.  */
    172     result = read_fd (STDIN_FILENO,
    173 		      print_file_name ? "{standard input}" : NULL,
    174 		      (fstat64 (STDIN_FILENO, &st) == 0 && S_ISREG (st.st_mode))
    175 		      ? st.st_size : INT64_C (0x7fffffffffffffff));
    176   else
    177     do
    178       {
    179 	int fd = (strcmp (argv[remaining], "-") == 0
    180 		  ? STDIN_FILENO : open (argv[remaining], O_RDONLY));
    181 	if (unlikely (fd == -1))
    182 	  {
    183 	    error (0, errno, gettext ("cannot open '%s'"), argv[remaining]);
    184 	    result = 1;
    185 	  }
    186 	else
    187 	  {
    188 	    const char *fname = print_file_name ? argv[remaining] : NULL;
    189 	    int fstat_fail = fstat64 (fd, &st);
    190 	    off64_t fdlen = (fstat_fail
    191 			     ? INT64_C (0x7fffffffffffffff) : st.st_size);
    192 	    if (fdlen > (off64_t) min_len_bytes)
    193 	      {
    194 		Elf *elf = NULL;
    195 		if (entire_file
    196 		    || fstat_fail
    197 		    || !S_ISREG (st.st_mode)
    198 		    || (elf = elf_begin (fd, ELF_C_READ, NULL)) == NULL
    199 		    || elf_kind (elf) != ELF_K_ELF)
    200 		  result |= read_fd (fd, fname, fdlen);
    201 		else
    202 		  result |= read_elf (elf, fd, fname, fdlen);
    203 
    204 		/* This call will succeed even if ELF is NULL.  */
    205 		elf_end (elf);
    206 	      }
    207 
    208 	    if (strcmp (argv[remaining], "-") != 0)
    209 	      close (fd);
    210 	  }
    211 
    212 	if (elfmap != NULL && elfmap != MAP_FAILED)
    213 	  munmap (elfmap, elfmap_size);
    214 	elfmap = NULL;
    215       }
    216     while (++remaining < argc);
    217 
    218   return result;
    219 }
    220 
    221 
    222 /* Print the version information.  */
    223 static void
    224 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
    225 {
    226   fprintf (stream, "strings (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
    227   fprintf (stream, gettext ("\
    228 Copyright (C) %s Red Hat, Inc.\n\
    229 This is free software; see the source for copying conditions.  There is NO\n\
    230 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
    231 "), "2012");
    232   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
    233 }
    234 
    235 
    236 /* Handle program arguments.  */
    237 static error_t
    238 parse_opt (int key, char *arg,
    239 	   struct argp_state *state __attribute__ ((unused)))
    240 {
    241   switch (key)
    242     {
    243     case 'a':
    244       entire_file = true;
    245       break;
    246 
    247     case 'e':
    248       /* We expect a string of one character.  */
    249       switch (arg[1] != '\0' ? '\0' : arg[0])
    250 	{
    251 	case 's':
    252 	case 'S':
    253 	  char_7bit = arg[0] == 's';
    254 	  bytes_per_char = 1;
    255 	  break;
    256 
    257 	case 'b':
    258 	case 'B':
    259 	  big_endian = true;
    260 	  /* FALLTHROUGH */
    261 
    262 	case 'l':
    263 	case 'L':
    264 	  bytes_per_char = isupper (arg[0]) ? 4 : 2;
    265 	  break;
    266 
    267 	default:
    268 	  error (0, 0, gettext ("invalid value '%s' for %s parameter"),
    269 		 arg, "-e");
    270 	  argp_help (&argp, stderr, ARGP_HELP_SEE, "strings");
    271 	  return ARGP_ERR_UNKNOWN;
    272 	}
    273       break;
    274 
    275     case 'f':
    276       print_file_name = true;
    277       break;
    278 
    279     case 'n':
    280       min_len = atoi (arg);
    281       break;
    282 
    283     case 'o':
    284       goto octfmt;
    285 
    286     case 't':
    287       switch (arg[0])
    288 	{
    289 	case 'd':
    290 	  locfmt = "%7" PRId64 " ";
    291 	  break;
    292 
    293 	case 'o':
    294 	octfmt:
    295 	  locfmt = "%7" PRIo64 " ";
    296 	  break;
    297 
    298 	case 'x':
    299 	  locfmt = "%7" PRIx64 " ";
    300 	  break;
    301 
    302 	default:
    303 	  error (0, 0, gettext ("invalid value '%s' for %s parameter"),
    304 		 arg, "-t");
    305 	  argp_help (&argp, stderr, ARGP_HELP_SEE, "strings");
    306 	  return ARGP_ERR_UNKNOWN;
    307 	}
    308       break;
    309 
    310     case ARGP_KEY_FINI:
    311       /* Compute the length in bytes of any match.  */
    312       if (min_len <= 0 || min_len > INT_MAX / bytes_per_char)
    313 	error (EXIT_FAILURE, 0,
    314 	       gettext ("invalid minimum length of matched string size"));
    315       min_len_bytes = min_len * bytes_per_char;
    316       break;
    317 
    318     default:
    319       return ARGP_ERR_UNKNOWN;
    320     }
    321   return 0;
    322 }
    323 
    324 
    325 static void
    326 process_chunk_mb (const char *fname, const unsigned char *buf, off64_t to,
    327 		  size_t len, char **unprinted)
    328 {
    329   size_t curlen = *unprinted == NULL ? 0 : strlen (*unprinted);
    330   const unsigned char *start = buf;
    331   while (len >= bytes_per_char)
    332     {
    333       uint32_t ch;
    334 
    335       if (bytes_per_char == 2)
    336 	{
    337 	  if (big_endian)
    338 	    ch = buf[0] << 8 | buf[1];
    339 	  else
    340 	    ch = buf[1] << 8 | buf[0];
    341 	}
    342       else
    343 	{
    344 	  if (big_endian)
    345 	    ch = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
    346 	  else
    347 	    ch = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
    348 	}
    349 
    350       if (ch <= 255 && (isprint (ch) || ch == '\t'))
    351 	{
    352 	  ++buf;
    353 	  ++curlen;
    354 	}
    355       else
    356 	{
    357 	  if (curlen >= min_len)
    358 	    {
    359 	      /* We found a match.  */
    360 	      if (unlikely (fname != NULL))
    361 		{
    362 		  fputs_unlocked (fname, stdout);
    363 		  fputs_unlocked (": ", stdout);
    364 		}
    365 
    366 	      if (unlikely (locfmt != NULL))
    367 		printf (locfmt, (int64_t) to - len - (buf - start));
    368 
    369 	      if (unlikely (*unprinted != NULL))
    370 		{
    371 		  fputs_unlocked (*unprinted, stdout);
    372 		  free (*unprinted);
    373 		  *unprinted = NULL;
    374 		}
    375 
    376 	      /* There is no sane way of printing the string.  If we
    377 		 assume the file data is encoded in UCS-2/UTF-16 or
    378 		 UCS-4/UTF-32 respectively we could covert the string.
    379 		 But there is no such guarantee.  */
    380 	      fwrite_unlocked (start, 1, buf - start, stdout);
    381 	      putc_unlocked ('\n', stdout);
    382 	    }
    383 
    384 	  start = ++buf;
    385 	  curlen =  0;
    386 
    387 	  if (len <= min_len)
    388 	    break;
    389 	}
    390 
    391       --len;
    392     }
    393 
    394   if (curlen != 0)
    395     *unprinted = xstrndup ((const char *) start, curlen);
    396 }
    397 
    398 
    399 static void
    400 process_chunk (const char *fname, const unsigned char *buf, off64_t to,
    401 	       size_t len, char **unprinted)
    402 {
    403   /* We are not going to slow the check down for the 2- and 4-byte
    404      encodings.  Handle them special.  */
    405   if (unlikely (bytes_per_char != 1))
    406     {
    407       process_chunk_mb (fname, buf, to, len, unprinted);
    408       return;
    409     }
    410 
    411   size_t curlen = *unprinted == NULL ? 0 : strlen (*unprinted);
    412   const unsigned char *start = buf;
    413   while (len > 0)
    414     {
    415       if ((isprint (*buf) || *buf == '\t') && (! char_7bit || *buf <= 127))
    416 	{
    417 	  ++buf;
    418 	  ++curlen;
    419 	}
    420       else
    421 	{
    422 	  if (curlen >= min_len)
    423 	    {
    424 	      /* We found a match.  */
    425 	      if (likely (fname != NULL))
    426 		{
    427 		  fputs_unlocked (fname, stdout);
    428 		  fputs_unlocked (": ", stdout);
    429 		}
    430 
    431 	      if (likely (locfmt != NULL))
    432 		printf (locfmt, (int64_t) to - len - (buf - start));
    433 
    434 	      if (unlikely (*unprinted != NULL))
    435 		{
    436 		  fputs_unlocked (*unprinted, stdout);
    437 		  free (*unprinted);
    438 		  *unprinted = NULL;
    439 		}
    440 	      fwrite_unlocked (start, 1, buf - start, stdout);
    441 	      putc_unlocked ('\n', stdout);
    442 	    }
    443 
    444 	  start = ++buf;
    445 	  curlen =  0;
    446 
    447 	  if (len <= min_len)
    448 	    break;
    449 	}
    450 
    451       --len;
    452     }
    453 
    454   if (curlen != 0)
    455     *unprinted = xstrndup ((const char *) start, curlen);
    456 }
    457 
    458 
    459 /* Map a file in as large chunks as possible.  */
    460 static void *
    461 map_file (int fd, off64_t start_off, off64_t fdlen, size_t *map_sizep)
    462 {
    463 #if _MUDFLAP
    464   (void) fd;
    465   (void) start_off;
    466   (void) fdlen;
    467   (void) map_sizep;
    468   return MAP_FAILED;
    469 #else
    470   /* Maximum size we mmap.  We use an #ifdef to avoid overflows on
    471      32-bit machines.  64-bit machines these days do not have usable
    472      address spaces larger than about 43 bits.  Not that any file
    473      should be that large.  */
    474 # if SIZE_MAX > 0xffffffff
    475   const size_t mmap_max = 0x4000000000lu;
    476 # else
    477   const size_t mmap_max = 0x40000000lu;
    478 # endif
    479 
    480   /* Try to mmap the file.  */
    481   size_t map_size = MIN ((off64_t) mmap_max, fdlen);
    482   const size_t map_size_min = MAX (MAX (SIZE_MAX / 16, 2 * ps),
    483 				   roundup (2 * min_len_bytes + 1, ps));
    484   void *mem;
    485   while (1)
    486     {
    487       /* We map the memory for reading only here.  Since we will
    488 	 always look at every byte of the file it makes sense to
    489 	 use MAP_POPULATE.  */
    490       mem = mmap64 (NULL, map_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE,
    491 		    fd, start_off);
    492       if (mem != MAP_FAILED)
    493 	{
    494 	  /* We will go through the mapping sequentially.  */
    495 	  (void) posix_madvise (mem, map_size, POSIX_MADV_SEQUENTIAL);
    496 	  break;
    497 	}
    498       if (errno != EINVAL && errno != ENOMEM)
    499 	/* This is an error other than the lack of address space.  */
    500 	break;
    501 
    502       /* Maybe the size of the mapping is too big.  Try again.  */
    503       map_size /= 2;
    504       if (map_size < map_size_min)
    505 	/* That size should have fit.  */
    506 	break;
    507     }
    508 
    509   *map_sizep = map_size;
    510   return mem;
    511 #endif
    512 }
    513 
    514 
    515 /* Read the file without mapping.  */
    516 static int
    517 read_block_no_mmap (int fd, const char *fname, off64_t from, off64_t fdlen)
    518 {
    519   char *unprinted = NULL;
    520 #define CHUNKSIZE 65536
    521   unsigned char *buf = xmalloc (CHUNKSIZE + min_len_bytes
    522 				+ bytes_per_char - 1);
    523   size_t ntrailer = 0;
    524   int result = 0;
    525   while (fdlen > 0)
    526     {
    527       ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + ntrailer,
    528 					    MIN (fdlen, CHUNKSIZE)));
    529       if (n == 0)
    530 	{
    531 	  /* There are less than MIN_LEN+1 bytes left so there cannot be
    532 	     another match.  */
    533 	  assert (unprinted == NULL || ntrailer == 0);
    534 	  break;
    535 	}
    536       if (unlikely (n < 0))
    537 	{
    538 	  /* Something went wrong.  */
    539 	  result = 1;
    540 	  break;
    541 	}
    542 
    543       /* Account for the number of bytes read in this round.  */
    544       fdlen -= n;
    545 
    546       /* Do not use the signed N value.  Note that the addition cannot
    547 	 overflow.  */
    548       size_t nb = (size_t) n + ntrailer;
    549       if (nb >= min_len_bytes)
    550 	{
    551 	  /* We only use complete characters.  */
    552 	  nb &= ~(bytes_per_char - 1);
    553 
    554 	  process_chunk (fname, buf, from + nb, nb, &unprinted);
    555 
    556 	  /* If the last bytes of the buffer (modulo the character
    557 	     size) have been printed we are not copying them.  */
    558 	  size_t to_keep = unprinted != NULL ? 0 : min_len_bytes;
    559 
    560 	  memmove (buf, buf + nb - to_keep, to_keep);
    561 	  ntrailer = to_keep;
    562 	  from += nb;
    563 	}
    564       else
    565 	ntrailer = nb;
    566     }
    567 
    568   free (buf);
    569 
    570   /* Don't print anything we collected so far.  There is no
    571      terminating NUL byte.  */
    572   free (unprinted);
    573 
    574   return result;
    575 }
    576 
    577 
    578 static int
    579 read_block (int fd, const char *fname, off64_t fdlen, off64_t from, off64_t to)
    580 {
    581   if (elfmap == NULL)
    582     {
    583       /* We need a completely new mapping.  */
    584       elfmap_off = from & ~(ps - 1);
    585       elfmap_base = elfmap = map_file (fd, elfmap_off, fdlen, &elfmap_size);
    586 
    587       if (unlikely (elfmap == MAP_FAILED))
    588 	/* Let the kernel know we are going to read everything in sequence.  */
    589 	(void) posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
    590     }
    591 
    592   if (unlikely (elfmap == MAP_FAILED))
    593     {
    594       /* Read from the file descriptor.  For this we must position the
    595 	 read pointer.  */
    596       // XXX Eventually add flag which avoids this if the position
    597       // XXX is known to match.
    598       if (from != 0 && lseek64 (fd, from, SEEK_SET) != from)
    599 	error (EXIT_FAILURE, errno, gettext ("lseek64 failed"));
    600 
    601       return read_block_no_mmap (fd, fname, from, to - from);
    602     }
    603 
    604   assert ((off64_t) min_len_bytes < fdlen);
    605 
    606   if (to < (off64_t) elfmap_off || from > (off64_t) (elfmap_off + elfmap_size))
    607     {
    608       /* The existing mapping cannot fit at all.  Map the new area.
    609 	 We always map the full range of ELFMAP_SIZE bytes even if
    610 	 this extend beyond the end of the file.  The Linux kernel
    611 	 handles this OK if the access pages are not touched.  */
    612       elfmap_off = from & ~(ps - 1);
    613       if (mmap64 (elfmap, elfmap_size, PROT_READ,
    614 		  MAP_PRIVATE | MAP_POPULATE | MAP_FIXED, fd, from)
    615 	  == MAP_FAILED)
    616 	error (EXIT_FAILURE, errno, gettext ("re-mmap failed"));
    617       elfmap_base = elfmap;
    618     }
    619 
    620   char *unprinted = NULL;
    621 
    622   /* Use the existing mapping as much as possible.  If necessary, map
    623      new pages.  */
    624   if (from >= (off64_t) elfmap_off
    625       && from < (off64_t) (elfmap_off + elfmap_size))
    626     /* There are at least a few bytes in this mapping which we can
    627        use.  */
    628     process_chunk (fname, elfmap_base + (from - elfmap_off),
    629 		   MIN (to, (off64_t) (elfmap_off + elfmap_size)),
    630 		   MIN (to, (off64_t) (elfmap_off + elfmap_size)) - from,
    631 		   &unprinted);
    632 
    633   if (to > (off64_t) (elfmap_off + elfmap_size))
    634     {
    635       unsigned char *remap_base = elfmap_base;
    636       size_t read_now = elfmap_size - (elfmap_base - elfmap);
    637 
    638       assert (from >= (off64_t) elfmap_off
    639 	      && from < (off64_t) (elfmap_off + elfmap_size));
    640       off64_t handled_to = elfmap_off + elfmap_size;
    641       assert (elfmap == elfmap_base
    642 	      || (elfmap_base - elfmap
    643 		  == (ptrdiff_t) ((min_len_bytes + ps - 1) & ~(ps - 1))));
    644       if (elfmap == elfmap_base)
    645 	{
    646 	  size_t keep_area = (min_len_bytes + ps - 1) & ~(ps - 1);
    647 	  assert (elfmap_size >= keep_area + ps);
    648 	  /* The keep area is used for the content of the previous
    649 	     buffer we have to keep.  This means copying those bytes
    650 	     and for this we have to make the data writable.  */
    651 	  if (unlikely (mprotect (elfmap, keep_area, PROT_READ | PROT_WRITE)
    652 			!= 0))
    653 	    error (EXIT_FAILURE, errno, gettext ("mprotect failed"));
    654 
    655 	  elfmap_base = elfmap + keep_area;
    656 	}
    657 
    658       while (1)
    659 	{
    660 	  /* Map the rest of the file, eventually again in pieces.
    661 	     We speed things up with a nice Linux feature.  Note
    662 	     that we have at least two pages mapped.  */
    663 	  size_t to_keep = unprinted != NULL ? 0 : min_len_bytes;
    664 
    665 	  assert (read_now >= to_keep);
    666 	  memmove (elfmap_base - to_keep,
    667 		   remap_base + read_now - to_keep, to_keep);
    668 	  remap_base = elfmap_base;
    669 
    670 	  assert ((elfmap_size - (elfmap_base - elfmap)) % bytes_per_char
    671 		  == 0);
    672 	  read_now = MIN (to - handled_to,
    673 			  (ptrdiff_t) elfmap_size - (elfmap_base - elfmap));
    674 
    675 	  assert (handled_to % ps == 0);
    676 	  assert (handled_to % bytes_per_char == 0);
    677 	  if (mmap64 (remap_base, read_now, PROT_READ,
    678 		      MAP_PRIVATE | MAP_POPULATE | MAP_FIXED, fd, handled_to)
    679 	      == MAP_FAILED)
    680 	    error (EXIT_FAILURE, errno, gettext ("re-mmap failed"));
    681 	  elfmap_off = handled_to;
    682 
    683 	  process_chunk (fname, remap_base - to_keep,
    684 			 elfmap_off + (read_now & ~(bytes_per_char - 1)),
    685 			 to_keep + (read_now & ~(bytes_per_char - 1)),
    686 			 &unprinted);
    687 	  handled_to += read_now;
    688 	  if (handled_to >= to)
    689 	    break;
    690 	}
    691     }
    692 
    693   /* Don't print anything we collected so far.  There is no
    694      terminating NUL byte.  */
    695   free (unprinted);
    696 
    697   return 0;
    698 }
    699 
    700 
    701 static int
    702 read_fd (int fd, const char *fname, off64_t fdlen)
    703 {
    704   return read_block (fd, fname, fdlen, 0, fdlen);
    705 }
    706 
    707 
    708 static int
    709 read_elf (Elf *elf, int fd, const char *fname, off64_t fdlen)
    710 {
    711   assert (fdlen >= 0);
    712 
    713   /* We will look at each section separately.  The ELF file is not
    714      mmapped.  The libelf implementation will load the needed parts on
    715      demand.  Since we only interate over the section header table the
    716      memory consumption at this stage is kept minimal.  */
    717   Elf_Scn *scn = elf_nextscn (elf, NULL);
    718   if (scn == NULL)
    719     return read_fd (fd, fname, fdlen);
    720 
    721   int result = 0;
    722   do
    723     {
    724       GElf_Shdr shdr_mem;
    725       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    726 
    727       /* Only look in sections which are loaded at runtime and
    728 	 actually have content.  */
    729       if (shdr != NULL && shdr->sh_type != SHT_NOBITS
    730 	  && (shdr->sh_flags & SHF_ALLOC) != 0)
    731 	result |= read_block (fd, fname, fdlen, shdr->sh_offset,
    732 			      shdr->sh_offset + shdr->sh_size);
    733     }
    734   while ((scn = elf_nextscn (elf, scn)) != NULL);
    735 
    736   if (elfmap != NULL && elfmap != MAP_FAILED)
    737     munmap (elfmap, elfmap_size);
    738   elfmap = NULL;
    739 
    740   return result;
    741 }
    742 
    743 
    744 #include "debugpred.h"
    745