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