f60e4b4d70a968fa5a25059bcf06ee836246a58e
[platform/upstream/elfutils.git] / src / strings.c
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
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
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
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
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
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 *
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
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
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
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
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"