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)
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
21 /* Usage: strings [options] file...
26 - Do not scan only the initialized data section of object files.
29 -f Print the name of the file before each string.
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.
37 -t {o,x,d} Print the offset within the file before each string,
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}
45 Select character encoding: 7-bit-character, 8-bit-character,
46 bigendian 16-bit, littleendian 16-bit, bigendian 32-bit,
51 Specify a non-default object file format.
54 -h Print the usage message on the standard output.
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>. */
66 #include "libiberty.h"
67 #include "safe-ctype.h"
71 #define STRING_ISGRAPHIC(c) \
74 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
80 /* The BFD section flags that identify an initialized data section. */
81 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
84 typedef off64_t file_off
;
85 #define file_open(s,m) fopen64(s, m)
87 typedef off_t file_off
;
88 #define file_open(s,m) fopen(s, m)
91 typedef struct stat64 statbuf
;
92 #define file_stat(f,s) stat64(f, s)
94 typedef struct stat statbuf
;
95 #define file_stat(f,s) stat(f, s)
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. */
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'},
136 /* Records the size of a named file so that we
137 do not repeatedly run bfd_stat() on it. */
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
)
159 bfd_boolean files_given
= FALSE
;
162 #if defined (HAVE_SETLOCALE)
163 setlocale (LC_ALL
, "");
165 bindtextdomain (PACKAGE
, LOCALEDIR
);
166 textdomain (PACKAGE
);
168 program_name
= argv
[0];
169 xmalloc_set_program_name (program_name
);
171 expandargv (&argc
, &argv
);
174 print_addresses
= FALSE
;
175 print_filenames
= FALSE
;
176 datasection_only
= TRUE
;
180 while ((optc
= getopt_long (argc
, argv
, "afhHn:ot:e:T:Vv0123456789",
181 long_options
, (int *) 0)) != EOF
)
186 datasection_only
= FALSE
;
190 print_filenames
= TRUE
;
198 string_min
= (int) strtoul (optarg
, &s
, 0);
199 if (s
!= NULL
&& *s
!= 0)
200 fatal (_("invalid integer argument %s"), optarg
);
204 print_addresses
= TRUE
;
209 print_addresses
= TRUE
;
210 if (optarg
[1] != '\0')
236 if (optarg
[1] != '\0')
238 encoding
= optarg
[0];
243 print_version ("strings");
250 string_min
= (int) strtoul (argv
[optind
- 1] + 1, &s
, 0);
251 if (s
!= NULL
&& *s
!= 0)
252 fatal (_("invalid integer argument %s"), argv
[optind
- 1] + 1);
258 fatal (_("invalid minimum string length %d"), string_min
);
279 set_default_bfd_target ();
283 datasection_only
= FALSE
;
284 SET_BINARY (fileno (stdin
));
285 print_strings ("{standard input}", stdin
, 0, 0, 0, (char *) NULL
);
290 for (; optind
< argc
; ++optind
)
292 if (strcmp (argv
[optind
], "-") == 0)
293 datasection_only
= FALSE
;
297 exit_status
|= strings_file (argv
[optind
]) == FALSE
;
305 return (exit_status
);
308 /* Scan section SECT of the file ABFD, whose printable name is in
309 ARG->filename and whose size might be in ARG->filesize. If it
310 contains initialized data set `got_a_section' and print the
313 FIXME: We ought to be able to return error codes/messages for
314 certain conditions. */
317 strings_a_section (bfd
*abfd
, asection
*sect
, void *arg
)
319 filename_and_size_t
* filename_and_sizep
;
320 bfd_size_type
*filesizep
;
321 bfd_size_type sectsize
;
324 if ((sect
->flags
& DATA_FLAGS
) != DATA_FLAGS
)
327 sectsize
= bfd_get_section_size (sect
);
332 /* Get the size of the file. This might have been cached for us. */
333 filename_and_sizep
= (filename_and_size_t
*) arg
;
334 filesizep
= & filename_and_sizep
->filesize
;
340 if (bfd_stat (abfd
, &st
))
343 /* Cache the result so that we do not repeatedly stat this file. */
344 *filesizep
= st
.st_size
;
347 /* Compare the size of the section against the size of the file.
348 If the section is bigger then the file must be corrupt and
349 we should not try dumping it. */
350 if (sectsize
>= *filesizep
)
353 mem
= xmalloc (sectsize
);
355 if (bfd_get_section_contents (abfd
, sect
, mem
, (file_ptr
) 0, sectsize
))
357 got_a_section
= TRUE
;
359 print_strings (filename_and_sizep
->filename
, NULL
, sect
->filepos
,
366 /* Scan all of the sections in FILE, and print the strings
367 in the initialized data section(s).
369 Return TRUE if successful,
370 FALSE if not (such as if FILE is not an object file). */
373 strings_object_file (const char *file
)
375 filename_and_size_t filename_and_size
;
378 abfd
= bfd_openr (file
, target
);
381 /* Treat the file as a non-object file. */
384 /* This call is mainly for its side effect of reading in the sections.
385 We follow the traditional behavior of `strings' in that we don't
386 complain if we don't recognize a file to be an object file. */
387 if (!bfd_check_format (abfd
, bfd_object
))
393 got_a_section
= FALSE
;
394 filename_and_size
.filename
= file
;
395 filename_and_size
.filesize
= 0;
396 bfd_map_over_sections (abfd
, strings_a_section
, & filename_and_size
);
398 if (!bfd_close (abfd
))
404 return got_a_section
;
407 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
410 strings_file (char *file
)
414 if (file_stat (file
, &st
) < 0)
417 non_fatal (_("'%s': No such file"), file
);
419 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
420 file
, strerror (errno
));
424 /* If we weren't told to scan the whole file,
425 try to open it as an object file and only look at
426 initialized data sections. If that fails, fall back to the
428 if (!datasection_only
|| !strings_object_file (file
))
432 stream
= file_open (file
, FOPEN_RB
);
435 fprintf (stderr
, "%s: ", program_name
);
440 print_strings (file
, stream
, (file_off
) 0, 0, 0, (char *) 0);
442 if (fclose (stream
) == EOF
)
444 fprintf (stderr
, "%s: ", program_name
);
453 /* Read the next character, return EOF if none available.
454 Assume that STREAM is positioned so that the next byte read
455 is at address ADDRESS in the file.
457 If STREAM is NULL, do not read from it.
458 The caller can supply a buffer of characters
459 to be processed before the data in STREAM.
460 MAGIC is the address of the buffer and
461 MAGICCOUNT is how many characters are in it. */
464 get_char (FILE *stream
, file_off
*address
, int *magiccount
, char **magic
)
468 unsigned char buf
[4];
470 for (i
= 0; i
< encoding_bytes
; i
++)
482 /* Only use getc_unlocked if we found a declaration for it.
483 Otherwise, libc is not thread safe by default, and we
484 should not use it. */
486 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
487 c
= getc_unlocked (stream
);
506 r
= (buf
[0] << 8) | buf
[1];
509 r
= buf
[0] | (buf
[1] << 8);
512 r
= ((long) buf
[0] << 24) | ((long) buf
[1] << 16) |
513 ((long) buf
[2] << 8) | buf
[3];
516 r
= buf
[0] | ((long) buf
[1] << 8) | ((long) buf
[2] << 16) |
517 ((long) buf
[3] << 24);
527 /* Find the strings in file FILENAME, read from STREAM.
528 Assume that STREAM is positioned so that the next byte read
529 is at address ADDRESS in the file.
530 Stop reading at address STOP_POINT in the file, if nonzero.
532 If STREAM is NULL, do not read from it.
533 The caller can supply a buffer of characters
534 to be processed before the data in STREAM.
535 MAGIC is the address of the buffer and
536 MAGICCOUNT is how many characters are in it.
537 Those characters come at address ADDRESS and the data in STREAM follow. */
540 print_strings (const char *filename
, FILE *stream
, file_off address
,
541 int stop_point
, int magiccount
, char *magic
)
543 char *buf
= (char *) xmalloc (sizeof (char) * (string_min
+ 1));
551 /* See if the next `string_min' chars are all graphic chars. */
553 if (stop_point
&& address
>= stop_point
)
556 for (i
= 0; i
< string_min
; i
++)
558 c
= get_char (stream
, &address
, &magiccount
, &magic
);
561 if (! STRING_ISGRAPHIC (c
))
562 /* Found a non-graphic. Try again starting with next char. */
567 /* We found a run of `string_min' graphic characters. Print up
568 to the next non-graphic character. */
571 printf ("%s: ", filename
);
573 switch (address_radix
)
576 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
577 if (sizeof (start
) > sizeof (long))
580 printf ("%7llo ", (unsigned long long) start
);
582 printf ("%7I64o ", (unsigned long long) start
);
586 #elif !BFD_HOST_64BIT_LONG
587 if (start
!= (unsigned long) start
)
588 printf ("++%7lo ", (unsigned long) start
);
591 printf ("%7lo ", (unsigned long) start
);
595 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
596 if (sizeof (start
) > sizeof (long))
599 printf ("%7lld ", (unsigned long long) start
);
601 printf ("%7I64d ", (unsigned long long) start
);
605 #elif !BFD_HOST_64BIT_LONG
606 if (start
!= (unsigned long) start
)
607 printf ("++%7ld ", (unsigned long) start
);
610 printf ("%7ld ", (long) start
);
614 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
615 if (sizeof (start
) > sizeof (long))
618 printf ("%7llx ", (unsigned long long) start
);
620 printf ("%7I64x ", (unsigned long long) start
);
624 #elif !BFD_HOST_64BIT_LONG
625 if (start
!= (unsigned long) start
)
626 printf ("%lx%8.8lx ", (unsigned long) (start
>> 32),
627 (unsigned long) (start
& 0xffffffff));
630 printf ("%7lx ", (unsigned long) start
);
639 c
= get_char (stream
, &address
, &magiccount
, &magic
);
642 if (! STRING_ISGRAPHIC (c
))
652 usage (FILE *stream
, int status
)
654 fprintf (stream
, _("Usage: %s [option(s)] [file(s)]\n"), program_name
);
655 fprintf (stream
, _(" Display printable strings in [file(s)] (stdin by default)\n"));
656 fprintf (stream
, _(" The options are:\n\
657 -a - --all Scan the entire file, not just the data section\n\
658 -f --print-file-name Print the name of the file before each string\n\
659 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
660 -<number> least [number] characters (default 4).\n\
661 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
662 -o An alias for --radix=o\n\
663 -T --target=<BFDNAME> Specify the binary file format\n\
664 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
665 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
666 @<file> Read options from <file>\n\
667 -h --help Display this information\n\
668 -v -V --version Print the program's version number\n"));
669 list_supported_targets (program_name
, stream
);
670 if (REPORT_BUGS_TO
[0] && status
== 0)
671 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);