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