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.
58 Written by Richard Stallman <rms@gnu.ai.mit.edu>
59 and David MacKenzie <djm@gnu.ai.mit.edu>. */
64 #include "libiberty.h"
65 #include "safe-ctype.h"
69 /* Some platforms need to put stdin into binary mode, to read
73 #define setmode _setmode
77 #define SET_BINARY(f) do { if (!isatty (f)) setmode (f, O_BINARY); } while (0)
81 #define STRING_ISGRAPHIC(c) \
84 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
90 /* The BFD section flags that identify an initialized data section. */
91 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
94 typedef off64_t file_off
;
95 #define file_open(s,m) fopen64(s, m)
97 typedef off_t file_off
;
98 #define file_open(s,m) fopen(s, m)
101 typedef struct stat64 statbuf
;
102 #define file_stat(f,s) stat64(f, s)
104 typedef struct stat statbuf
;
105 #define file_stat(f,s) stat(f, s)
108 /* Radix for printing addresses (must be 8, 10 or 16). */
109 static int address_radix
;
111 /* Minimum length of sequence of graphic chars to trigger output. */
112 static int string_min
;
114 /* TRUE means print address within file for each string. */
115 static bfd_boolean print_addresses
;
117 /* TRUE means print filename for each string. */
118 static bfd_boolean print_filenames
;
120 /* TRUE means for object files scan only the data section. */
121 static bfd_boolean datasection_only
;
123 /* TRUE if we found an initialized data section in the current file. */
124 static bfd_boolean got_a_section
;
126 /* The BFD object file format. */
129 /* The character encoding format. */
130 static char encoding
;
131 static int encoding_bytes
;
133 static struct option long_options
[] =
135 {"all", no_argument
, NULL
, 'a'},
136 {"print-file-name", no_argument
, NULL
, 'f'},
137 {"bytes", required_argument
, NULL
, 'n'},
138 {"radix", required_argument
, NULL
, 't'},
139 {"encoding", required_argument
, NULL
, 'e'},
140 {"target", required_argument
, NULL
, 'T'},
141 {"help", no_argument
, NULL
, 'h'},
142 {"version", no_argument
, NULL
, 'v'},
146 /* Records the size of a named file so that we
147 do not repeatedly run bfd_stat() on it. */
151 const char * filename
;
152 bfd_size_type filesize
;
153 } filename_and_size_t
;
155 static void strings_a_section (bfd
*, asection
*, void *);
156 static bfd_boolean
strings_object_file (const char *);
157 static bfd_boolean
strings_file (char *file
);
158 static void print_strings (const char *, FILE *, file_off
, int, int, char *);
159 static void usage (FILE *, int);
160 static long get_char (FILE *, file_off
*, int *, char **);
162 int main (int, char **);
165 main (int argc
, char **argv
)
169 bfd_boolean files_given
= FALSE
;
171 #if defined (HAVE_SETLOCALE)
172 setlocale (LC_ALL
, "");
174 bindtextdomain (PACKAGE
, LOCALEDIR
);
175 textdomain (PACKAGE
);
177 program_name
= argv
[0];
178 xmalloc_set_program_name (program_name
);
180 expandargv (&argc
, &argv
);
183 print_addresses
= FALSE
;
184 print_filenames
= FALSE
;
185 datasection_only
= TRUE
;
189 while ((optc
= getopt_long (argc
, argv
, "afhHn:ot:e:T:Vv0123456789",
190 long_options
, (int *) 0)) != EOF
)
195 datasection_only
= FALSE
;
199 print_filenames
= TRUE
;
207 string_min
= (int) strtoul (optarg
, NULL
, 0);
211 print_addresses
= TRUE
;
216 print_addresses
= TRUE
;
217 if (optarg
[1] != '\0')
243 if (optarg
[1] != '\0')
245 encoding
= optarg
[0];
250 print_version ("strings");
257 string_min
= (int) strtoul (argv
[optind
- 1] + 1, NULL
, 0);
263 fatal (_("invalid minimum string length %d"), string_min
);
284 set_default_bfd_target ();
288 datasection_only
= FALSE
;
290 SET_BINARY (fileno (stdin
));
292 print_strings ("{standard input}", stdin
, 0, 0, 0, (char *) NULL
);
297 for (; optind
< argc
; ++optind
)
299 if (strcmp (argv
[optind
], "-") == 0)
300 datasection_only
= FALSE
;
304 exit_status
|= strings_file (argv
[optind
]) == FALSE
;
312 return (exit_status
);
315 /* Scan section SECT of the file ABFD, whose printable name is in
316 ARG->filename and whose size might be in ARG->filesize. If it
317 contains initialized data set `got_a_section' and print the
320 FIXME: We ought to be able to return error codes/messages for
321 certain conditions. */
324 strings_a_section (bfd
*abfd
, asection
*sect
, void *arg
)
326 filename_and_size_t
* filename_and_sizep
;
327 bfd_size_type
*filesizep
;
328 bfd_size_type sectsize
;
331 if ((sect
->flags
& DATA_FLAGS
) != DATA_FLAGS
)
334 sectsize
= bfd_get_section_size (sect
);
339 /* Get the size of the file. This might have been cached for us. */
340 filename_and_sizep
= (filename_and_size_t
*) arg
;
341 filesizep
= & filename_and_sizep
->filesize
;
347 if (bfd_stat (abfd
, &st
))
350 /* Cache the result so that we do not repeatedly stat this file. */
351 *filesizep
= st
.st_size
;
354 /* Compare the size of the section against the size of the file.
355 If the section is bigger then the file must be corrupt and
356 we should not try dumping it. */
357 if (sectsize
>= *filesizep
)
360 mem
= xmalloc (sectsize
);
362 if (bfd_get_section_contents (abfd
, sect
, mem
, (file_ptr
) 0, sectsize
))
364 got_a_section
= TRUE
;
366 print_strings (filename_and_sizep
->filename
, NULL
, sect
->filepos
,
373 /* Scan all of the sections in FILE, and print the strings
374 in the initialized data section(s).
376 Return TRUE if successful,
377 FALSE if not (such as if FILE is not an object file). */
380 strings_object_file (const char *file
)
382 filename_and_size_t filename_and_size
;
385 abfd
= bfd_openr (file
, target
);
388 /* Treat the file as a non-object file. */
391 /* This call is mainly for its side effect of reading in the sections.
392 We follow the traditional behavior of `strings' in that we don't
393 complain if we don't recognize a file to be an object file. */
394 if (!bfd_check_format (abfd
, bfd_object
))
400 got_a_section
= FALSE
;
401 filename_and_size
.filename
= file
;
402 filename_and_size
.filesize
= 0;
403 bfd_map_over_sections (abfd
, strings_a_section
, & filename_and_size
);
405 if (!bfd_close (abfd
))
411 return got_a_section
;
414 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
417 strings_file (char *file
)
421 if (file_stat (file
, &st
) < 0)
424 non_fatal (_("'%s': No such file"), file
);
426 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
427 file
, strerror (errno
));
431 /* If we weren't told to scan the whole file,
432 try to open it as an object file and only look at
433 initialized data sections. If that fails, fall back to the
435 if (!datasection_only
|| !strings_object_file (file
))
439 stream
= file_open (file
, FOPEN_RB
);
442 fprintf (stderr
, "%s: ", program_name
);
447 print_strings (file
, stream
, (file_off
) 0, 0, 0, (char *) 0);
449 if (fclose (stream
) == EOF
)
451 fprintf (stderr
, "%s: ", program_name
);
460 /* Read the next character, return EOF if none available.
461 Assume that STREAM is positioned so that the next byte read
462 is at address ADDRESS in the file.
464 If STREAM is NULL, do not read from it.
465 The caller can supply a buffer of characters
466 to be processed before the data in STREAM.
467 MAGIC is the address of the buffer and
468 MAGICCOUNT is how many characters are in it. */
471 get_char (FILE *stream
, file_off
*address
, int *magiccount
, char **magic
)
475 unsigned char buf
[4];
477 for (i
= 0; i
< encoding_bytes
; i
++)
489 /* Only use getc_unlocked if we found a declaration for it.
490 Otherwise, libc is not thread safe by default, and we
491 should not use it. */
493 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
494 c
= getc_unlocked (stream
);
513 r
= (buf
[0] << 8) | buf
[1];
516 r
= buf
[0] | (buf
[1] << 8);
519 r
= ((long) buf
[0] << 24) | ((long) buf
[1] << 16) |
520 ((long) buf
[2] << 8) | buf
[3];
523 r
= buf
[0] | ((long) buf
[1] << 8) | ((long) buf
[2] << 16) |
524 ((long) buf
[3] << 24);
534 /* Find the strings in file FILENAME, read from STREAM.
535 Assume that STREAM is positioned so that the next byte read
536 is at address ADDRESS in the file.
537 Stop reading at address STOP_POINT in the file, if nonzero.
539 If STREAM is NULL, do not read from it.
540 The caller can supply a buffer of characters
541 to be processed before the data in STREAM.
542 MAGIC is the address of the buffer and
543 MAGICCOUNT is how many characters are in it.
544 Those characters come at address ADDRESS and the data in STREAM follow. */
547 print_strings (const char *filename
, FILE *stream
, file_off address
,
548 int stop_point
, int magiccount
, char *magic
)
550 char *buf
= (char *) xmalloc (sizeof (char) * (string_min
+ 1));
558 /* See if the next `string_min' chars are all graphic chars. */
560 if (stop_point
&& address
>= stop_point
)
563 for (i
= 0; i
< string_min
; i
++)
565 c
= get_char (stream
, &address
, &magiccount
, &magic
);
568 if (! STRING_ISGRAPHIC (c
))
569 /* Found a non-graphic. Try again starting with next char. */
574 /* We found a run of `string_min' graphic characters. Print up
575 to the next non-graphic character. */
578 printf ("%s: ", filename
);
580 switch (address_radix
)
583 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
584 if (sizeof (start
) > sizeof (long))
587 printf ("%7llo ", (unsigned long long) start
);
589 printf ("%7I64o ", (unsigned long long) start
);
593 #elif !BFD_HOST_64BIT_LONG
594 if (start
!= (unsigned long) start
)
595 printf ("++%7lo ", (unsigned long) start
);
598 printf ("%7lo ", (unsigned long) start
);
602 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
603 if (sizeof (start
) > sizeof (long))
606 printf ("%7lld ", (unsigned long long) start
);
608 printf ("%7I64d ", (unsigned long long) start
);
612 #elif !BFD_HOST_64BIT_LONG
613 if (start
!= (unsigned long) start
)
614 printf ("++%7ld ", (unsigned long) start
);
617 printf ("%7ld ", (long) start
);
621 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
622 if (sizeof (start
) > sizeof (long))
625 printf ("%7llx ", (unsigned long long) start
);
627 printf ("%7I64x ", (unsigned long long) start
);
631 #elif !BFD_HOST_64BIT_LONG
632 if (start
!= (unsigned long) start
)
633 printf ("%lx%8.8lx ", (unsigned long) (start
>> 32),
634 (unsigned long) (start
& 0xffffffff));
637 printf ("%7lx ", (unsigned long) start
);
646 c
= get_char (stream
, &address
, &magiccount
, &magic
);
649 if (! STRING_ISGRAPHIC (c
))
659 usage (FILE *stream
, int status
)
661 fprintf (stream
, _("Usage: %s [option(s)] [file(s)]\n"), program_name
);
662 fprintf (stream
, _(" Display printable strings in [file(s)] (stdin by default)\n"));
663 fprintf (stream
, _(" The options are:\n\
664 -a - --all Scan the entire file, not just the data section\n\
665 -f --print-file-name Print the name of the file before each string\n\
666 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
667 -<number> least [number] characters (default 4).\n\
668 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
669 -o An alias for --radix=o\n\
670 -T --target=<BFDNAME> Specify the binary file format\n\
671 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
672 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
673 @<file> Read options from <file>\n\
674 -h --help Display this information\n\
675 -v --version Print the program's version number\n"));
676 list_supported_targets (program_name
, stream
);
677 if (REPORT_BUGS_TO
[0] && status
== 0)
678 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);