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 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
20 /* Usage: strings [options] file...
25 - Do not scan only the initialized data section of object files.
28 -f Print the name of the file before each string.
32 -min-len Print graphic char sequences, MIN-LEN or more bytes long,
33 that are followed by a NUL or a newline. Default is 4.
36 -t {o,x,d} Print the offset within the file before each string,
39 -o Like -to. (Some other implementations have -o like -to,
40 others like -td. We chose one arbitrarily.)
42 --encoding={s,S,b,l,B,L}
44 Select character encoding: 7-bit-character, 8-bit-character,
45 bigendian 16-bit, littleendian 16-bit, bigendian 32-bit,
50 Specify a non-default object file format.
53 -h Print the usage message on the standard output.
56 -v Print the program version number.
64 #include "libiberty.h"
65 #include "safe-ctype.h"
69 /* Some platforms need to put stdin into binary mode, to read
74 #define O_BINARY _O_BINARY
75 #define setmode _setmode
82 #define SET_BINARY(f) do { if (!isatty (f)) setmode (f,O_BINARY); } while (0)
86 #define STRING_ISGRAPHIC(c) \
89 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
95 /* The BFD section flags that identify an initialized data section. */
96 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
99 typedef off64_t file_off;
100 #define file_open(s,m) fopen64(s, m)
102 typedef off_t file_off;
103 #define file_open(s,m) fopen(s, m)
106 typedef struct stat64 statbuf;
107 #define file_stat(f,s) stat64(f, s)
109 typedef struct stat statbuf;
110 #define file_stat(f,s) stat(f, s)
113 /* Radix for printing addresses (must be 8, 10 or 16). */
114 static int address_radix;
116 /* Minimum length of sequence of graphic chars to trigger output. */
117 static int string_min;
119 /* TRUE means print address within file for each string. */
120 static bfd_boolean print_addresses;
122 /* TRUE means print filename for each string. */
123 static bfd_boolean print_filenames;
125 /* TRUE means for object files scan only the data section. */
126 static bfd_boolean datasection_only;
128 /* TRUE if we found an initialized data section in the current file. */
129 static bfd_boolean got_a_section;
131 /* The BFD object file format. */
134 /* The character encoding format. */
135 static char encoding;
136 static int encoding_bytes;
138 static struct option long_options[] =
140 {"all", no_argument, NULL, 'a'},
141 {"print-file-name", no_argument, NULL, 'f'},
142 {"bytes", required_argument, NULL, 'n'},
143 {"radix", required_argument, NULL, 't'},
144 {"encoding", required_argument, NULL, 'e'},
145 {"target", required_argument, NULL, 'T'},
146 {"help", no_argument, NULL, 'h'},
147 {"version", no_argument, NULL, 'v'},
151 /* Records the size of a named file so that we
152 do not repeatedly run bfd_stat() on it. */
156 const char * filename;
157 bfd_size_type filesize;
158 } filename_and_size_t;
160 static void strings_a_section (bfd *, asection *, void *);
161 static bfd_boolean strings_object_file (const char *);
162 static bfd_boolean strings_file (char *file);
163 static void print_strings (const char *, FILE *, file_off, int, int, char *);
164 static void usage (FILE *, int);
165 static long get_char (FILE *, file_off *, int *, char **);
167 int main (int, char **);
170 main (int argc, char **argv)
174 bfd_boolean files_given = FALSE;
176 #if defined (HAVE_SETLOCALE)
177 setlocale (LC_ALL, "");
179 bindtextdomain (PACKAGE, LOCALEDIR);
180 textdomain (PACKAGE);
182 program_name = argv[0];
183 xmalloc_set_program_name (program_name);
185 expandargv (&argc, &argv);
188 print_addresses = FALSE;
189 print_filenames = FALSE;
190 datasection_only = TRUE;
194 while ((optc = getopt_long (argc, argv, "afhHn:ot:e:T:Vv0123456789",
195 long_options, (int *) 0)) != EOF)
200 datasection_only = FALSE;
204 print_filenames = TRUE;
212 string_min = (int) strtoul (optarg, NULL, 0);
216 print_addresses = TRUE;
221 print_addresses = TRUE;
222 if (optarg[1] != '\0')
248 if (optarg[1] != '\0')
250 encoding = optarg[0];
255 print_version ("strings");
262 string_min = (int) strtoul (argv[optind - 1] + 1, NULL, 0);
268 fatal (_("invalid minimum string length %d"), string_min);
289 set_default_bfd_target ();
293 datasection_only = FALSE;
295 SET_BINARY (fileno (stdin));
297 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
302 for (; optind < argc; ++optind)
304 if (strcmp (argv[optind], "-") == 0)
305 datasection_only = FALSE;
309 exit_status |= strings_file (argv[optind]) == FALSE;
317 return (exit_status);
320 /* Scan section SECT of the file ABFD, whose printable name is in
321 ARG->filename and whose size might be in ARG->filesize. If it
322 contains initialized data set `got_a_section' and print the
325 FIXME: We ought to be able to return error codes/messages for
326 certain conditions. */
329 strings_a_section (bfd *abfd, asection *sect, void *arg)
331 filename_and_size_t * filename_and_sizep;
332 bfd_size_type *filesizep;
333 bfd_size_type sectsize;
336 if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
339 sectsize = bfd_get_section_size (sect);
344 /* Get the size of the file. This might have been cached for us. */
345 filename_and_sizep = (filename_and_size_t *) arg;
346 filesizep = & filename_and_sizep->filesize;
352 if (bfd_stat (abfd, &st))
355 /* Cache the result so that we do not repeatedly stat this file. */
356 *filesizep = st.st_size;
359 /* Compare the size of the section against the size of the file.
360 If the section is bigger then the file must be corrupt and
361 we should not try dumping it. */
362 if (sectsize >= *filesizep)
365 mem = xmalloc (sectsize);
367 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
369 got_a_section = TRUE;
371 print_strings (filename_and_sizep->filename, NULL, sect->filepos,
378 /* Scan all of the sections in FILE, and print the strings
379 in the initialized data section(s).
381 Return TRUE if successful,
382 FALSE if not (such as if FILE is not an object file). */
385 strings_object_file (const char *file)
387 filename_and_size_t filename_and_size;
390 abfd = bfd_openr (file, target);
393 /* Treat the file as a non-object file. */
396 /* This call is mainly for its side effect of reading in the sections.
397 We follow the traditional behavior of `strings' in that we don't
398 complain if we don't recognize a file to be an object file. */
399 if (!bfd_check_format (abfd, bfd_object))
405 got_a_section = FALSE;
406 filename_and_size.filename = file;
407 filename_and_size.filesize = 0;
408 bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
410 if (!bfd_close (abfd))
416 return got_a_section;
419 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
422 strings_file (char *file)
426 if (file_stat (file, &st) < 0)
429 non_fatal (_("'%s': No such file"), file);
431 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
432 file, strerror (errno));
436 /* If we weren't told to scan the whole file,
437 try to open it as an object file and only look at
438 initialized data sections. If that fails, fall back to the
440 if (!datasection_only || !strings_object_file (file))
444 stream = file_open (file, FOPEN_RB);
447 fprintf (stderr, "%s: ", program_name);
452 print_strings (file, stream, (file_off) 0, 0, 0, (char *) 0);
454 if (fclose (stream) == EOF)
456 fprintf (stderr, "%s: ", program_name);
465 /* Read the next character, return EOF if none available.
466 Assume that STREAM is positioned so that the next byte read
467 is at address ADDRESS in the file.
469 If STREAM is NULL, do not read from it.
470 The caller can supply a buffer of characters
471 to be processed before the data in STREAM.
472 MAGIC is the address of the buffer and
473 MAGICCOUNT is how many characters are in it. */
476 get_char (FILE *stream, file_off *address, int *magiccount, char **magic)
480 unsigned char buf[4];
482 for (i = 0; i < encoding_bytes; i++)
494 /* Only use getc_unlocked if we found a declaration for it.
495 Otherwise, libc is not thread safe by default, and we
496 should not use it. */
498 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
499 c = getc_unlocked (stream);
518 r = (buf[0] << 8) | buf[1];
521 r = buf[0] | (buf[1] << 8);
524 r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
525 ((long) buf[2] << 8) | buf[3];
528 r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
529 ((long) buf[3] << 24);
539 /* Find the strings in file FILENAME, read from STREAM.
540 Assume that STREAM is positioned so that the next byte read
541 is at address ADDRESS in the file.
542 Stop reading at address STOP_POINT in the file, if nonzero.
544 If STREAM is NULL, do not read from it.
545 The caller can supply a buffer of characters
546 to be processed before the data in STREAM.
547 MAGIC is the address of the buffer and
548 MAGICCOUNT is how many characters are in it.
549 Those characters come at address ADDRESS and the data in STREAM follow. */
552 print_strings (const char *filename, FILE *stream, file_off address,
553 int stop_point, int magiccount, char *magic)
555 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
563 /* See if the next `string_min' chars are all graphic chars. */
565 if (stop_point && address >= stop_point)
568 for (i = 0; i < string_min; i++)
570 c = get_char (stream, &address, &magiccount, &magic);
573 if (! STRING_ISGRAPHIC (c))
574 /* Found a non-graphic. Try again starting with next char. */
579 /* We found a run of `string_min' graphic characters. Print up
580 to the next non-graphic character. */
583 printf ("%s: ", filename);
585 switch (address_radix)
588 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
589 if (sizeof (start) > sizeof (long))
592 printf ("%7llo ", (unsigned long long) start);
594 printf ("%7I64o ", (unsigned long long) start);
598 #elif !BFD_HOST_64BIT_LONG
599 if (start != (unsigned long) start)
600 printf ("++%7lo ", (unsigned long) start);
603 printf ("%7lo ", (unsigned long) start);
607 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
608 if (sizeof (start) > sizeof (long))
611 printf ("%7lld ", (unsigned long long) start);
613 printf ("%7I64d ", (unsigned long long) start);
617 #elif !BFD_HOST_64BIT_LONG
618 if (start != (unsigned long) start)
619 printf ("++%7ld ", (unsigned long) start);
622 printf ("%7ld ", (long) start);
626 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
627 if (sizeof (start) > sizeof (long))
630 printf ("%7llx ", (unsigned long long) start);
632 printf ("%7I64x ", (unsigned long long) start);
636 #elif !BFD_HOST_64BIT_LONG
637 if (start != (unsigned long) start)
638 printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
639 (unsigned long) (start & 0xffffffff));
642 printf ("%7lx ", (unsigned long) start);
651 c = get_char (stream, &address, &magiccount, &magic);
654 if (! STRING_ISGRAPHIC (c))
664 usage (FILE *stream, int status)
666 fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
667 fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
668 fprintf (stream, _(" The options are:\n\
669 -a - --all Scan the entire file, not just the data section\n\
670 -f --print-file-name Print the name of the file before each string\n\
671 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
672 -<number> least [number] characters (default 4).\n\
673 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
674 -o An alias for --radix=o\n\
675 -T --target=<BFDNAME> Specify the binary file format\n\
676 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
677 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
678 @<file> Read options from <file>\n\
679 -h --help Display this information\n\
680 -v --version Print the program's version number\n"));
681 list_supported_targets (program_name, stream);
682 if (REPORT_BUGS_TO[0] && status == 0)
683 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);