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 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 2, 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,
49 Specify a non-default object file format.
52 -h Print the usage message on the standard output.
55 -v Print the program version number.
57 Written by Richard Stallman <rms@gnu.ai.mit.edu>
58 and David MacKenzie <djm@gnu.ai.mit.edu>. */
68 #include "libiberty.h"
69 #include "safe-ctype.h"
72 /* Some platforms need to put stdin into binary mode, to read
77 #define O_BINARY _O_BINARY
78 #define setmode _setmode
85 #define SET_BINARY(f) do { if (!isatty (f)) setmode (f,O_BINARY); } while (0)
89 #define STRING_ISGRAPHIC(c) \
92 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
98 /* The BFD section flags that identify an initialized data section. */
99 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
102 typedef off64_t file_off;
103 #define file_open(s,m) fopen64(s, m)
105 typedef off_t file_off;
106 #define file_open(s,m) fopen(s, m)
109 typedef struct stat64 statbuf;
110 #define file_stat(f,s) stat64(f, s)
112 typedef struct stat statbuf;
113 #define file_stat(f,s) stat(f, s)
116 /* Radix for printing addresses (must be 8, 10 or 16). */
117 static int address_radix;
119 /* Minimum length of sequence of graphic chars to trigger output. */
120 static int string_min;
122 /* TRUE means print address within file for each string. */
123 static bfd_boolean print_addresses;
125 /* TRUE means print filename for each string. */
126 static bfd_boolean print_filenames;
128 /* TRUE means for object files scan only the data section. */
129 static bfd_boolean datasection_only;
131 /* TRUE if we found an initialized data section in the current file. */
132 static bfd_boolean got_a_section;
134 /* The BFD object file format. */
137 /* The character encoding format. */
138 static char encoding;
139 static int encoding_bytes;
141 static struct option long_options[] =
143 {"all", no_argument, NULL, 'a'},
144 {"print-file-name", no_argument, NULL, 'f'},
145 {"bytes", required_argument, NULL, 'n'},
146 {"radix", required_argument, NULL, 't'},
147 {"encoding", required_argument, NULL, 'e'},
148 {"target", required_argument, NULL, 'T'},
149 {"help", no_argument, NULL, 'h'},
150 {"version", no_argument, NULL, 'v'},
154 /* Records the size of a named file so that we
155 do not repeatedly run bfd_stat() on it. */
159 const char * filename;
160 bfd_size_type filesize;
161 } filename_and_size_t;
163 static void strings_a_section (bfd *, asection *, void *);
164 static bfd_boolean strings_object_file (const char *);
165 static bfd_boolean strings_file (char *file);
166 static int integer_arg (char *s);
167 static void print_strings (const char *, FILE *, file_off, int, int, char *);
168 static void usage (FILE *, int);
169 static long get_char (FILE *, file_off *, int *, char **);
171 int main (int, char **);
174 main (int argc, char **argv)
178 bfd_boolean files_given = FALSE;
180 #if defined (HAVE_SETLOCALE)
181 setlocale (LC_ALL, "");
183 bindtextdomain (PACKAGE, LOCALEDIR);
184 textdomain (PACKAGE);
186 program_name = argv[0];
187 xmalloc_set_program_name (program_name);
189 print_addresses = FALSE;
190 print_filenames = FALSE;
191 datasection_only = TRUE;
195 while ((optc = getopt_long (argc, argv, "afhHn:ot:e:Vv0123456789",
196 long_options, (int *) 0)) != EOF)
201 datasection_only = FALSE;
205 print_filenames = TRUE;
213 string_min = integer_arg (optarg);
215 fatal (_("invalid number %s"), optarg);
219 print_addresses = TRUE;
224 print_addresses = TRUE;
225 if (optarg[1] != '\0')
251 if (optarg[1] != '\0')
253 encoding = optarg[0];
258 print_version ("strings");
266 string_min = optc - '0';
268 string_min = string_min * 10 + optc - '0';
295 set_default_bfd_target ();
299 datasection_only = FALSE;
301 SET_BINARY (fileno (stdin));
303 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
308 for (; optind < argc; ++optind)
310 if (strcmp (argv[optind], "-") == 0)
311 datasection_only = FALSE;
315 exit_status |= strings_file (argv[optind]) == FALSE;
323 return (exit_status);
326 /* Scan section SECT of the file ABFD, whose printable name is in
327 ARG->filename and whose size might be in ARG->filesize. If it
328 contains initialized data set `got_a_section' and print the
331 FIXME: We ought to be able to return error codes/messages for
332 certain conditions. */
335 strings_a_section (bfd *abfd, asection *sect, void *arg)
337 filename_and_size_t * filename_and_sizep;
338 bfd_size_type *filesizep;
339 bfd_size_type sectsize;
342 if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
345 sectsize = bfd_get_section_size (sect);
350 /* Get the size of the file. This might have been cached for us. */
351 filename_and_sizep = (filename_and_size_t *) arg;
352 filesizep = & filename_and_sizep->filesize;
358 if (bfd_stat (abfd, &st))
361 /* Cache the result so that we do not repeatedly stat this file. */
362 *filesizep = st.st_size;
365 /* Compare the size of the section against the size of the file.
366 If the section is bigger then the file must be corrupt and
367 we should not try dumping it. */
368 if (sectsize >= *filesizep)
371 mem = xmalloc (sectsize);
373 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
375 got_a_section = TRUE;
377 print_strings (filename_and_sizep->filename, NULL, sect->filepos,
384 /* Scan all of the sections in FILE, and print the strings
385 in the initialized data section(s).
387 Return TRUE if successful,
388 FALSE if not (such as if FILE is not an object file). */
391 strings_object_file (const char *file)
393 filename_and_size_t filename_and_size;
396 abfd = bfd_openr (file, target);
399 /* Treat the file as a non-object file. */
402 /* This call is mainly for its side effect of reading in the sections.
403 We follow the traditional behavior of `strings' in that we don't
404 complain if we don't recognize a file to be an object file. */
405 if (!bfd_check_format (abfd, bfd_object))
411 got_a_section = FALSE;
412 filename_and_size.filename = file;
413 filename_and_size.filesize = 0;
414 bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
416 if (!bfd_close (abfd))
422 return got_a_section;
425 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
428 strings_file (char *file)
432 if (file_stat (file, &st) < 0)
435 non_fatal (_("'%s': No such file"), file);
437 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
438 file, strerror (errno));
442 /* If we weren't told to scan the whole file,
443 try to open it as an object file and only look at
444 initialized data sections. If that fails, fall back to the
446 if (!datasection_only || !strings_object_file (file))
450 stream = file_open (file, FOPEN_RB);
453 fprintf (stderr, "%s: ", program_name);
458 print_strings (file, stream, (file_off) 0, 0, 0, (char *) 0);
460 if (fclose (stream) == EOF)
462 fprintf (stderr, "%s: ", program_name);
471 /* Read the next character, return EOF if none available.
472 Assume that STREAM is positioned so that the next byte read
473 is at address ADDRESS in the file.
475 If STREAM is NULL, do not read from it.
476 The caller can supply a buffer of characters
477 to be processed before the data in STREAM.
478 MAGIC is the address of the buffer and
479 MAGICCOUNT is how many characters are in it. */
482 get_char (FILE *stream, file_off *address, int *magiccount, char **magic)
486 unsigned char buf[4];
488 for (i = 0; i < encoding_bytes; i++)
500 /* Only use getc_unlocked if we found a declaration for it.
501 Otherwise, libc is not thread safe by default, and we
502 should not use it. */
504 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
505 c = getc_unlocked (stream);
524 r = (buf[0] << 8) | buf[1];
527 r = buf[0] | (buf[1] << 8);
530 r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
531 ((long) buf[2] << 8) | buf[3];
534 r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
535 ((long) buf[3] << 24);
545 /* Find the strings in file FILENAME, read from STREAM.
546 Assume that STREAM is positioned so that the next byte read
547 is at address ADDRESS in the file.
548 Stop reading at address STOP_POINT in the file, if nonzero.
550 If STREAM is NULL, do not read from it.
551 The caller can supply a buffer of characters
552 to be processed before the data in STREAM.
553 MAGIC is the address of the buffer and
554 MAGICCOUNT is how many characters are in it.
555 Those characters come at address ADDRESS and the data in STREAM follow. */
558 print_strings (const char *filename, FILE *stream, file_off address,
559 int stop_point, int magiccount, char *magic)
561 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
569 /* See if the next `string_min' chars are all graphic chars. */
571 if (stop_point && address >= stop_point)
574 for (i = 0; i < string_min; i++)
576 c = get_char (stream, &address, &magiccount, &magic);
579 if (! STRING_ISGRAPHIC (c))
580 /* Found a non-graphic. Try again starting with next char. */
585 /* We found a run of `string_min' graphic characters. Print up
586 to the next non-graphic character. */
589 printf ("%s: ", filename);
591 switch (address_radix)
594 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
595 if (sizeof (start) > sizeof (long))
596 printf ("%7Lo ", (unsigned long long) start);
599 # if !BFD_HOST_64BIT_LONG
600 if (start != (unsigned long) start)
601 printf ("++%7lo ", (unsigned long) start);
605 printf ("%7lo ", (unsigned long) start);
609 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
610 if (sizeof (start) > sizeof (long))
611 printf ("%7Ld ", (unsigned long long) start);
614 # if !BFD_HOST_64BIT_LONG
615 if (start != (unsigned long) start)
616 printf ("++%7ld ", (unsigned long) start);
620 printf ("%7ld ", (long) start);
624 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
625 if (sizeof (start) > sizeof (long))
626 printf ("%7Lx ", (unsigned long long) start);
629 # if !BFD_HOST_64BIT_LONG
630 if (start != (unsigned long) start)
631 printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
632 (unsigned long) (start & 0xffffffff));
636 printf ("%7lx ", (unsigned long) start);
645 c = get_char (stream, &address, &magiccount, &magic);
648 if (! STRING_ISGRAPHIC (c))
657 /* Parse string S as an integer, using decimal radix by default,
658 but allowing octal and hex numbers as in C. */
661 integer_arg (char *s)
670 else if (*++p == 'x')
679 while (((c = *p++) >= '0' && c <= '9')
680 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
683 if (c >= '0' && c <= '9')
686 value += (c & ~40) - 'A';
697 fatal (_("invalid integer argument %s"), s);
703 usage (FILE *stream, int status)
705 fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
706 fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
707 fprintf (stream, _(" The options are:\n\
708 -a - --all Scan the entire file, not just the data section\n\
709 -f --print-file-name Print the name of the file before each string\n\
710 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
711 -<number> least [number] characters (default 4).\n\
712 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
713 -o An alias for --radix=o\n\
714 -T --target=<BFDNAME> Specify the binary file format\n\
715 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
716 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
717 -h --help Display this information\n\
718 -v --version Print the program's version number\n"));
719 list_supported_targets (program_name, stream);
721 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);