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