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