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
main(int argc,char * argv[])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
parse_opt(int key,char * arg,struct argp_state * state)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
process_chunk_mb(const char * fname,const unsigned char * buf,off_t to,size_t len,char ** unprinted)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
process_chunk(const char * fname,const unsigned char * buf,off_t to,size_t len,char ** unprinted)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 *
map_file(int fd,off_t start_off,off_t fdlen,size_t * map_sizep)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
read_block_no_mmap(int fd,const char * fname,off_t from,off_t fdlen)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
read_block(int fd,const char * fname,off_t fdlen,off_t from,off_t to)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
read_fd(int fd,const char * fname,off_t fdlen)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
read_elf(Elf * elf,int fd,const char * fname,off_t fdlen)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"
748