• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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
main(int argc,char * argv[])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
print_version(FILE * stream,struct argp_state * state)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
parse_opt(int key,char * arg,struct argp_state * state)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
process_chunk_mb(const char * fname,const unsigned char * buf,off_t to,size_t len,char ** unprinted)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
process_chunk(const char * fname,const unsigned char * buf,off_t to,size_t len,char ** unprinted)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 *
map_file(int fd,off_t start_off,off_t fdlen,size_t * map_sizep)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
read_block_no_mmap(int fd,const char * fname,off_t from,off_t fdlen)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
read_block(int fd,const char * fname,off_t fdlen,off_t from,off_t to)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
read_fd(int fd,const char * fname,off_t fdlen)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
read_elf(Elf * elf,int fd,const char * fname,off_t fdlen)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