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 expandargv (&argc
, &argv
);
192 print_addresses
= FALSE
;
193 print_filenames
= FALSE
;
194 datasection_only
= TRUE
;
198 while ((optc
= getopt_long (argc
, argv
, "afhHn:ot:e:Vv0123456789",
199 long_options
, (int *) 0)) != EOF
)
204 datasection_only
= FALSE
;
208 print_filenames
= TRUE
;
216 string_min
= integer_arg (optarg
);
218 fatal (_("invalid number %s"), optarg
);
222 print_addresses
= TRUE
;
227 print_addresses
= TRUE
;
228 if (optarg
[1] != '\0')
254 if (optarg
[1] != '\0')
256 encoding
= optarg
[0];
261 print_version ("strings");
269 string_min
= optc
- '0';
271 string_min
= string_min
* 10 + optc
- '0';
298 set_default_bfd_target ();
302 datasection_only
= FALSE
;
304 SET_BINARY (fileno (stdin
));
306 print_strings ("{standard input}", stdin
, 0, 0, 0, (char *) NULL
);
311 for (; optind
< argc
; ++optind
)
313 if (strcmp (argv
[optind
], "-") == 0)
314 datasection_only
= FALSE
;
318 exit_status
|= strings_file (argv
[optind
]) == FALSE
;
326 return (exit_status
);
329 /* Scan section SECT of the file ABFD, whose printable name is in
330 ARG->filename and whose size might be in ARG->filesize. If it
331 contains initialized data set `got_a_section' and print the
334 FIXME: We ought to be able to return error codes/messages for
335 certain conditions. */
338 strings_a_section (bfd
*abfd
, asection
*sect
, void *arg
)
340 filename_and_size_t
* filename_and_sizep
;
341 bfd_size_type
*filesizep
;
342 bfd_size_type sectsize
;
345 if ((sect
->flags
& DATA_FLAGS
) != DATA_FLAGS
)
348 sectsize
= bfd_get_section_size (sect
);
353 /* Get the size of the file. This might have been cached for us. */
354 filename_and_sizep
= (filename_and_size_t
*) arg
;
355 filesizep
= & filename_and_sizep
->filesize
;
361 if (bfd_stat (abfd
, &st
))
364 /* Cache the result so that we do not repeatedly stat this file. */
365 *filesizep
= st
.st_size
;
368 /* Compare the size of the section against the size of the file.
369 If the section is bigger then the file must be corrupt and
370 we should not try dumping it. */
371 if (sectsize
>= *filesizep
)
374 mem
= xmalloc (sectsize
);
376 if (bfd_get_section_contents (abfd
, sect
, mem
, (file_ptr
) 0, sectsize
))
378 got_a_section
= TRUE
;
380 print_strings (filename_and_sizep
->filename
, NULL
, sect
->filepos
,
387 /* Scan all of the sections in FILE, and print the strings
388 in the initialized data section(s).
390 Return TRUE if successful,
391 FALSE if not (such as if FILE is not an object file). */
394 strings_object_file (const char *file
)
396 filename_and_size_t filename_and_size
;
399 abfd
= bfd_openr (file
, target
);
402 /* Treat the file as a non-object file. */
405 /* This call is mainly for its side effect of reading in the sections.
406 We follow the traditional behavior of `strings' in that we don't
407 complain if we don't recognize a file to be an object file. */
408 if (!bfd_check_format (abfd
, bfd_object
))
414 got_a_section
= FALSE
;
415 filename_and_size
.filename
= file
;
416 filename_and_size
.filesize
= 0;
417 bfd_map_over_sections (abfd
, strings_a_section
, & filename_and_size
);
419 if (!bfd_close (abfd
))
425 return got_a_section
;
428 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
431 strings_file (char *file
)
435 if (file_stat (file
, &st
) < 0)
438 non_fatal (_("'%s': No such file"), file
);
440 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
441 file
, strerror (errno
));
445 /* If we weren't told to scan the whole file,
446 try to open it as an object file and only look at
447 initialized data sections. If that fails, fall back to the
449 if (!datasection_only
|| !strings_object_file (file
))
453 stream
= file_open (file
, FOPEN_RB
);
456 fprintf (stderr
, "%s: ", program_name
);
461 print_strings (file
, stream
, (file_off
) 0, 0, 0, (char *) 0);
463 if (fclose (stream
) == EOF
)
465 fprintf (stderr
, "%s: ", program_name
);
474 /* Read the next character, return EOF if none available.
475 Assume that STREAM is positioned so that the next byte read
476 is at address ADDRESS in the file.
478 If STREAM is NULL, do not read from it.
479 The caller can supply a buffer of characters
480 to be processed before the data in STREAM.
481 MAGIC is the address of the buffer and
482 MAGICCOUNT is how many characters are in it. */
485 get_char (FILE *stream
, file_off
*address
, int *magiccount
, char **magic
)
489 unsigned char buf
[4];
491 for (i
= 0; i
< encoding_bytes
; i
++)
503 /* Only use getc_unlocked if we found a declaration for it.
504 Otherwise, libc is not thread safe by default, and we
505 should not use it. */
507 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
508 c
= getc_unlocked (stream
);
527 r
= (buf
[0] << 8) | buf
[1];
530 r
= buf
[0] | (buf
[1] << 8);
533 r
= ((long) buf
[0] << 24) | ((long) buf
[1] << 16) |
534 ((long) buf
[2] << 8) | buf
[3];
537 r
= buf
[0] | ((long) buf
[1] << 8) | ((long) buf
[2] << 16) |
538 ((long) buf
[3] << 24);
548 /* Find the strings in file FILENAME, read from STREAM.
549 Assume that STREAM is positioned so that the next byte read
550 is at address ADDRESS in the file.
551 Stop reading at address STOP_POINT in the file, if nonzero.
553 If STREAM is NULL, do not read from it.
554 The caller can supply a buffer of characters
555 to be processed before the data in STREAM.
556 MAGIC is the address of the buffer and
557 MAGICCOUNT is how many characters are in it.
558 Those characters come at address ADDRESS and the data in STREAM follow. */
561 print_strings (const char *filename
, FILE *stream
, file_off address
,
562 int stop_point
, int magiccount
, char *magic
)
564 char *buf
= (char *) xmalloc (sizeof (char) * (string_min
+ 1));
572 /* See if the next `string_min' chars are all graphic chars. */
574 if (stop_point
&& address
>= stop_point
)
577 for (i
= 0; i
< string_min
; i
++)
579 c
= get_char (stream
, &address
, &magiccount
, &magic
);
582 if (! STRING_ISGRAPHIC (c
))
583 /* Found a non-graphic. Try again starting with next char. */
588 /* We found a run of `string_min' graphic characters. Print up
589 to the next non-graphic character. */
592 printf ("%s: ", filename
);
594 switch (address_radix
)
597 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
598 if (sizeof (start
) > sizeof (long))
599 printf ("%7Lo ", (unsigned long long) start
);
602 # if !BFD_HOST_64BIT_LONG
603 if (start
!= (unsigned long) start
)
604 printf ("++%7lo ", (unsigned long) start
);
608 printf ("%7lo ", (unsigned long) start
);
612 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
613 if (sizeof (start
) > sizeof (long))
614 printf ("%7Ld ", (unsigned long long) start
);
617 # if !BFD_HOST_64BIT_LONG
618 if (start
!= (unsigned long) start
)
619 printf ("++%7ld ", (unsigned long) start
);
623 printf ("%7ld ", (long) start
);
627 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
628 if (sizeof (start
) > sizeof (long))
629 printf ("%7Lx ", (unsigned long long) start
);
632 # if !BFD_HOST_64BIT_LONG
633 if (start
!= (unsigned long) start
)
634 printf ("%lx%8.8lx ", (unsigned long) (start
>> 32),
635 (unsigned long) (start
& 0xffffffff));
639 printf ("%7lx ", (unsigned long) start
);
648 c
= get_char (stream
, &address
, &magiccount
, &magic
);
651 if (! STRING_ISGRAPHIC (c
))
660 /* Parse string S as an integer, using decimal radix by default,
661 but allowing octal and hex numbers as in C. */
664 integer_arg (char *s
)
673 else if (*++p
== 'x')
682 while (((c
= *p
++) >= '0' && c
<= '9')
683 || (radix
== 16 && (c
& ~40) >= 'A' && (c
& ~40) <= 'Z'))
686 if (c
>= '0' && c
<= '9')
689 value
+= (c
& ~40) - 'A';
700 fatal (_("invalid integer argument %s"), s
);
706 usage (FILE *stream
, int status
)
708 fprintf (stream
, _("Usage: %s [option(s)] [file(s)]\n"), program_name
);
709 fprintf (stream
, _(" Display printable strings in [file(s)] (stdin by default)\n"));
710 fprintf (stream
, _(" The options are:\n\
711 -a - --all Scan the entire file, not just the data section\n\
712 -f --print-file-name Print the name of the file before each string\n\
713 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
714 -<number> least [number] characters (default 4).\n\
715 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
716 -o An alias for --radix=o\n\
717 -T --target=<BFDNAME> Specify the binary file format\n\
718 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
719 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
720 @<file> Read options from <file>\n\
721 -h --help Display this information\n\
722 -v --version Print the program's version number\n"));
723 list_supported_targets (program_name
, stream
);
725 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);