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