2009-07-02 Tristan Gingold <gingold@adacore.com>
[binutils.git] / binutils / strings.c
blob06fd8e995b72d1f772129b9d3ec8f2d1d79ab70f
1 /* strings -- print the strings of printable characters in files
2 Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
4 Free Software Foundation, Inc.
6 This program 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, or (at your option)
9 any later version.
11 This program is distributed in the hope that it will be useful,
12 but 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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 02110-1301, USA. */
21 /* Usage: strings [options] file...
23 Options:
24 --all
26 - Do not scan only the initialized data section of object files.
28 --print-file-name
29 -f Print the name of the file before each string.
31 --bytes=min-len
32 -n min-len
33 -min-len Print graphic char sequences, MIN-LEN or more bytes long,
34 that are followed by a NUL or a newline. Default is 4.
36 --radix={o,x,d}
37 -t {o,x,d} Print the offset within the file before each string,
38 in octal/hex/decimal.
40 -o Like -to. (Some other implementations have -o like -to,
41 others like -td. We chose one arbitrarily.)
43 --encoding={s,S,b,l,B,L}
44 -e {s,S,b,l,B,L}
45 Select character encoding: 7-bit-character, 8-bit-character,
46 bigendian 16-bit, littleendian 16-bit, bigendian 32-bit,
47 littleendian 32-bit.
49 --target=BFDNAME
50 -T {bfdname}
51 Specify a non-default object file format.
53 --help
54 -h Print the usage message on the standard output.
56 --version
58 -v Print the program version number.
60 Written by Richard Stallman <rms@gnu.ai.mit.edu>
61 and David MacKenzie <djm@gnu.ai.mit.edu>. */
63 #include "sysdep.h"
64 #include "bfd.h"
65 #include "getopt.h"
66 #include "libiberty.h"
67 #include "safe-ctype.h"
68 #include <sys/stat.h>
69 #include "bucomm.h"
71 #define STRING_ISGRAPHIC(c) \
72 ( (c) >= 0 \
73 && (c) <= 255 \
74 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
76 #ifndef errno
77 extern int errno;
78 #endif
80 /* The BFD section flags that identify an initialized data section. */
81 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
83 #ifdef HAVE_FOPEN64
84 typedef off64_t file_off;
85 #define file_open(s,m) fopen64(s, m)
86 #else
87 typedef off_t file_off;
88 #define file_open(s,m) fopen(s, m)
89 #endif
90 #ifdef HAVE_STAT64
91 typedef struct stat64 statbuf;
92 #define file_stat(f,s) stat64(f, s)
93 #else
94 typedef struct stat statbuf;
95 #define file_stat(f,s) stat(f, s)
96 #endif
98 /* Radix for printing addresses (must be 8, 10 or 16). */
99 static int address_radix;
101 /* Minimum length of sequence of graphic chars to trigger output. */
102 static int string_min;
104 /* TRUE means print address within file for each string. */
105 static bfd_boolean print_addresses;
107 /* TRUE means print filename for each string. */
108 static bfd_boolean print_filenames;
110 /* TRUE means for object files scan only the data section. */
111 static bfd_boolean datasection_only;
113 /* TRUE if we found an initialized data section in the current file. */
114 static bfd_boolean got_a_section;
116 /* The BFD object file format. */
117 static char *target;
119 /* The character encoding format. */
120 static char encoding;
121 static int encoding_bytes;
123 static struct option long_options[] =
125 {"all", no_argument, NULL, 'a'},
126 {"print-file-name", no_argument, NULL, 'f'},
127 {"bytes", required_argument, NULL, 'n'},
128 {"radix", required_argument, NULL, 't'},
129 {"encoding", required_argument, NULL, 'e'},
130 {"target", required_argument, NULL, 'T'},
131 {"help", no_argument, NULL, 'h'},
132 {"version", no_argument, NULL, 'v'},
133 {NULL, 0, NULL, 0}
136 /* Records the size of a named file so that we
137 do not repeatedly run bfd_stat() on it. */
139 typedef struct
141 const char * filename;
142 bfd_size_type filesize;
143 } filename_and_size_t;
145 static void strings_a_section (bfd *, asection *, void *);
146 static bfd_boolean strings_object_file (const char *);
147 static bfd_boolean strings_file (char *file);
148 static void print_strings (const char *, FILE *, file_off, int, int, char *);
149 static void usage (FILE *, int);
150 static long get_char (FILE *, file_off *, int *, char **);
152 int main (int, char **);
155 main (int argc, char **argv)
157 int optc;
158 int exit_status = 0;
159 bfd_boolean files_given = FALSE;
160 char *s;
161 int numeric_opt = 0;
163 #if defined (HAVE_SETLOCALE)
164 setlocale (LC_ALL, "");
165 #endif
166 bindtextdomain (PACKAGE, LOCALEDIR);
167 textdomain (PACKAGE);
169 program_name = argv[0];
170 xmalloc_set_program_name (program_name);
172 expandargv (&argc, &argv);
174 string_min = 4;
175 print_addresses = FALSE;
176 print_filenames = FALSE;
177 datasection_only = TRUE;
178 target = NULL;
179 encoding = 's';
181 while ((optc = getopt_long (argc, argv, "afhHn:ot:e:T:Vv0123456789",
182 long_options, (int *) 0)) != EOF)
184 switch (optc)
186 case 'a':
187 datasection_only = FALSE;
188 break;
190 case 'f':
191 print_filenames = TRUE;
192 break;
194 case 'H':
195 case 'h':
196 usage (stdout, 0);
198 case 'n':
199 string_min = (int) strtoul (optarg, &s, 0);
200 if (s != NULL && *s != 0)
201 fatal (_("invalid integer argument %s"), optarg);
202 break;
204 case 'o':
205 print_addresses = TRUE;
206 address_radix = 8;
207 break;
209 case 't':
210 print_addresses = TRUE;
211 if (optarg[1] != '\0')
212 usage (stderr, 1);
213 switch (optarg[0])
215 case 'o':
216 address_radix = 8;
217 break;
219 case 'd':
220 address_radix = 10;
221 break;
223 case 'x':
224 address_radix = 16;
225 break;
227 default:
228 usage (stderr, 1);
230 break;
232 case 'T':
233 target = optarg;
234 break;
236 case 'e':
237 if (optarg[1] != '\0')
238 usage (stderr, 1);
239 encoding = optarg[0];
240 break;
242 case 'V':
243 case 'v':
244 print_version ("strings");
245 break;
247 case '?':
248 usage (stderr, 1);
250 default:
251 numeric_opt = optind;
252 break;
256 if (numeric_opt != 0)
258 string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0);
259 if (s != NULL && *s != 0)
260 fatal (_("invalid integer argument %s"), argv[numeric_opt - 1] + 1);
262 if (string_min < 1)
263 fatal (_("invalid minimum string length %d"), string_min);
265 switch (encoding)
267 case 'S':
268 case 's':
269 encoding_bytes = 1;
270 break;
271 case 'b':
272 case 'l':
273 encoding_bytes = 2;
274 break;
275 case 'B':
276 case 'L':
277 encoding_bytes = 4;
278 break;
279 default:
280 usage (stderr, 1);
283 bfd_init ();
284 set_default_bfd_target ();
286 if (optind >= argc)
288 datasection_only = FALSE;
289 SET_BINARY (fileno (stdin));
290 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
291 files_given = TRUE;
293 else
295 for (; optind < argc; ++optind)
297 if (strcmp (argv[optind], "-") == 0)
298 datasection_only = FALSE;
299 else
301 files_given = TRUE;
302 exit_status |= strings_file (argv[optind]) == FALSE;
307 if (!files_given)
308 usage (stderr, 1);
310 return (exit_status);
313 /* Scan section SECT of the file ABFD, whose printable name is in
314 ARG->filename and whose size might be in ARG->filesize. If it
315 contains initialized data set `got_a_section' and print the
316 strings in it.
318 FIXME: We ought to be able to return error codes/messages for
319 certain conditions. */
321 static void
322 strings_a_section (bfd *abfd, asection *sect, void *arg)
324 filename_and_size_t * filename_and_sizep;
325 bfd_size_type *filesizep;
326 bfd_size_type sectsize;
327 void *mem;
329 if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
330 return;
332 sectsize = bfd_get_section_size (sect);
334 if (sectsize <= 0)
335 return;
337 /* Get the size of the file. This might have been cached for us. */
338 filename_and_sizep = (filename_and_size_t *) arg;
339 filesizep = & filename_and_sizep->filesize;
341 if (*filesizep == 0)
343 struct stat st;
345 if (bfd_stat (abfd, &st))
346 return;
348 /* Cache the result so that we do not repeatedly stat this file. */
349 *filesizep = st.st_size;
352 /* Compare the size of the section against the size of the file.
353 If the section is bigger then the file must be corrupt and
354 we should not try dumping it. */
355 if (sectsize >= *filesizep)
356 return;
358 mem = xmalloc (sectsize);
360 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
362 got_a_section = TRUE;
364 print_strings (filename_and_sizep->filename, NULL, sect->filepos,
365 0, sectsize, mem);
368 free (mem);
371 /* Scan all of the sections in FILE, and print the strings
372 in the initialized data section(s).
374 Return TRUE if successful,
375 FALSE if not (such as if FILE is not an object file). */
377 static bfd_boolean
378 strings_object_file (const char *file)
380 filename_and_size_t filename_and_size;
381 bfd *abfd;
383 abfd = bfd_openr (file, target);
385 if (abfd == NULL)
386 /* Treat the file as a non-object file. */
387 return FALSE;
389 /* This call is mainly for its side effect of reading in the sections.
390 We follow the traditional behavior of `strings' in that we don't
391 complain if we don't recognize a file to be an object file. */
392 if (!bfd_check_format (abfd, bfd_object))
394 bfd_close (abfd);
395 return FALSE;
398 got_a_section = FALSE;
399 filename_and_size.filename = file;
400 filename_and_size.filesize = 0;
401 bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
403 if (!bfd_close (abfd))
405 bfd_nonfatal (file);
406 return FALSE;
409 return got_a_section;
412 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
414 static bfd_boolean
415 strings_file (char *file)
417 statbuf st;
419 if (file_stat (file, &st) < 0)
421 if (errno == ENOENT)
422 non_fatal (_("'%s': No such file"), file);
423 else
424 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
425 file, strerror (errno));
426 return FALSE;
429 /* If we weren't told to scan the whole file,
430 try to open it as an object file and only look at
431 initialized data sections. If that fails, fall back to the
432 whole file. */
433 if (!datasection_only || !strings_object_file (file))
435 FILE *stream;
437 stream = file_open (file, FOPEN_RB);
438 if (stream == NULL)
440 fprintf (stderr, "%s: ", program_name);
441 perror (file);
442 return FALSE;
445 print_strings (file, stream, (file_off) 0, 0, 0, (char *) 0);
447 if (fclose (stream) == EOF)
449 fprintf (stderr, "%s: ", program_name);
450 perror (file);
451 return FALSE;
455 return TRUE;
458 /* Read the next character, return EOF if none available.
459 Assume that STREAM is positioned so that the next byte read
460 is at address ADDRESS in the file.
462 If STREAM is NULL, do not read from it.
463 The caller can supply a buffer of characters
464 to be processed before the data in STREAM.
465 MAGIC is the address of the buffer and
466 MAGICCOUNT is how many characters are in it. */
468 static long
469 get_char (FILE *stream, file_off *address, int *magiccount, char **magic)
471 int c, i;
472 long r = EOF;
473 unsigned char buf[4];
475 for (i = 0; i < encoding_bytes; i++)
477 if (*magiccount)
479 (*magiccount)--;
480 c = *(*magic)++;
482 else
484 if (stream == NULL)
485 return EOF;
487 /* Only use getc_unlocked if we found a declaration for it.
488 Otherwise, libc is not thread safe by default, and we
489 should not use it. */
491 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
492 c = getc_unlocked (stream);
493 #else
494 c = getc (stream);
495 #endif
496 if (c == EOF)
497 return EOF;
500 (*address)++;
501 buf[i] = c;
504 switch (encoding)
506 case 'S':
507 case 's':
508 r = buf[0];
509 break;
510 case 'b':
511 r = (buf[0] << 8) | buf[1];
512 break;
513 case 'l':
514 r = buf[0] | (buf[1] << 8);
515 break;
516 case 'B':
517 r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
518 ((long) buf[2] << 8) | buf[3];
519 break;
520 case 'L':
521 r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
522 ((long) buf[3] << 24);
523 break;
526 if (r == EOF)
527 return 0;
529 return r;
532 /* Find the strings in file FILENAME, read from STREAM.
533 Assume that STREAM is positioned so that the next byte read
534 is at address ADDRESS in the file.
535 Stop reading at address STOP_POINT in the file, if nonzero.
537 If STREAM is NULL, do not read from it.
538 The caller can supply a buffer of characters
539 to be processed before the data in STREAM.
540 MAGIC is the address of the buffer and
541 MAGICCOUNT is how many characters are in it.
542 Those characters come at address ADDRESS and the data in STREAM follow. */
544 static void
545 print_strings (const char *filename, FILE *stream, file_off address,
546 int stop_point, int magiccount, char *magic)
548 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
550 while (1)
552 file_off start;
553 int i;
554 long c;
556 /* See if the next `string_min' chars are all graphic chars. */
557 tryline:
558 if (stop_point && address >= stop_point)
559 break;
560 start = address;
561 for (i = 0; i < string_min; i++)
563 c = get_char (stream, &address, &magiccount, &magic);
564 if (c == EOF)
565 return;
566 if (! STRING_ISGRAPHIC (c))
567 /* Found a non-graphic. Try again starting with next char. */
568 goto tryline;
569 buf[i] = c;
572 /* We found a run of `string_min' graphic characters. Print up
573 to the next non-graphic character. */
575 if (print_filenames)
576 printf ("%s: ", filename);
577 if (print_addresses)
578 switch (address_radix)
580 case 8:
581 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
582 if (sizeof (start) > sizeof (long))
584 #ifndef __MSVCRT__
585 printf ("%7llo ", (unsigned long long) start);
586 #else
587 printf ("%7I64o ", (unsigned long long) start);
588 #endif
590 else
591 #elif !BFD_HOST_64BIT_LONG
592 if (start != (unsigned long) start)
593 printf ("++%7lo ", (unsigned long) start);
594 else
595 #endif
596 printf ("%7lo ", (unsigned long) start);
597 break;
599 case 10:
600 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
601 if (sizeof (start) > sizeof (long))
603 #ifndef __MSVCRT__
604 printf ("%7lld ", (unsigned long long) start);
605 #else
606 printf ("%7I64d ", (unsigned long long) start);
607 #endif
609 else
610 #elif !BFD_HOST_64BIT_LONG
611 if (start != (unsigned long) start)
612 printf ("++%7ld ", (unsigned long) start);
613 else
614 #endif
615 printf ("%7ld ", (long) start);
616 break;
618 case 16:
619 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
620 if (sizeof (start) > sizeof (long))
622 #ifndef __MSVCRT__
623 printf ("%7llx ", (unsigned long long) start);
624 #else
625 printf ("%7I64x ", (unsigned long long) start);
626 #endif
628 else
629 #elif !BFD_HOST_64BIT_LONG
630 if (start != (unsigned long) start)
631 printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
632 (unsigned long) (start & 0xffffffff));
633 else
634 #endif
635 printf ("%7lx ", (unsigned long) start);
636 break;
639 buf[i] = '\0';
640 fputs (buf, stdout);
642 while (1)
644 c = get_char (stream, &address, &magiccount, &magic);
645 if (c == EOF)
646 break;
647 if (! STRING_ISGRAPHIC (c))
648 break;
649 putchar (c);
652 putchar ('\n');
656 static void
657 usage (FILE *stream, int status)
659 fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
660 fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
661 fprintf (stream, _(" The options are:\n\
662 -a - --all Scan the entire file, not just the data section\n\
663 -f --print-file-name Print the name of the file before each string\n\
664 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
665 -<number> least [number] characters (default 4).\n\
666 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
667 -o An alias for --radix=o\n\
668 -T --target=<BFDNAME> Specify the binary file format\n\
669 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
670 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
671 @<file> Read options from <file>\n\
672 -h --help Display this information\n\
673 -v -V --version Print the program's version number\n"));
674 list_supported_targets (program_name, stream);
675 if (REPORT_BUGS_TO[0] && status == 0)
676 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
677 exit (status);