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