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