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 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,
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>. */
69 #include "libiberty.h"
70 #include "safe-ctype.h"
73 /* Some platforms need to put stdin into binary mode, to read
78 #define O_BINARY _O_BINARY
79 #define setmode _setmode
86 #define SET_BINARY(f) do { if (!isatty (f)) setmode (f,O_BINARY); } while (0)
90 #define STRING_ISGRAPHIC(c) \
93 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
99 /* The BFD section flags that identify an initialized data section. */
100 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
103 typedef off64_t file_off
;
104 #define file_open(s,m) fopen64(s, m)
106 typedef off_t file_off
;
107 #define file_open(s,m) fopen(s, m)
110 typedef struct stat64 statbuf
;
111 #define file_stat(f,s) stat64(f, s)
113 typedef struct stat statbuf
;
114 #define file_stat(f,s) stat(f, s)
117 /* Radix for printing addresses (must be 8, 10 or 16). */
118 static int address_radix
;
120 /* Minimum length of sequence of graphic chars to trigger output. */
121 static int string_min
;
123 /* TRUE means print address within file for each string. */
124 static bfd_boolean print_addresses
;
126 /* TRUE means print filename for each string. */
127 static bfd_boolean print_filenames
;
129 /* TRUE means for object files scan only the data section. */
130 static bfd_boolean datasection_only
;
132 /* TRUE if we found an initialized data section in the current file. */
133 static bfd_boolean got_a_section
;
135 /* The BFD object file format. */
138 /* The character encoding format. */
139 static char encoding
;
140 static int encoding_bytes
;
142 static struct option long_options
[] =
144 {"all", no_argument
, NULL
, 'a'},
145 {"print-file-name", no_argument
, NULL
, 'f'},
146 {"bytes", required_argument
, NULL
, 'n'},
147 {"radix", required_argument
, NULL
, 't'},
148 {"encoding", required_argument
, NULL
, 'e'},
149 {"target", required_argument
, NULL
, 'T'},
150 {"help", no_argument
, NULL
, 'h'},
151 {"version", no_argument
, NULL
, 'v'},
155 /* Records the size of a named file so that we
156 do not repeatedly run bfd_stat() on it. */
160 const char * filename
;
161 bfd_size_type filesize
;
162 } filename_and_size_t
;
164 static void strings_a_section (bfd
*, asection
*, void *);
165 static bfd_boolean
strings_object_file (const char *);
166 static bfd_boolean
strings_file (char *file
);
167 static int integer_arg (char *s
);
168 static void print_strings (const char *, FILE *, file_off
, int, int, char *);
169 static void usage (FILE *, int);
170 static long get_char (FILE *, file_off
*, int *, char **);
172 int main (int, char **);
175 main (int argc
, char **argv
)
179 bfd_boolean files_given
= FALSE
;
181 #if defined (HAVE_SETLOCALE)
182 setlocale (LC_ALL
, "");
184 bindtextdomain (PACKAGE
, LOCALEDIR
);
185 textdomain (PACKAGE
);
187 program_name
= argv
[0];
188 xmalloc_set_program_name (program_name
);
190 expandargv (&argc
, &argv
);
193 print_addresses
= FALSE
;
194 print_filenames
= FALSE
;
195 datasection_only
= TRUE
;
199 while ((optc
= getopt_long (argc
, argv
, "afhHn:ot:e:T:Vv0123456789",
200 long_options
, (int *) 0)) != EOF
)
205 datasection_only
= FALSE
;
209 print_filenames
= TRUE
;
217 string_min
= integer_arg (optarg
);
219 fatal (_("invalid number %s"), optarg
);
223 print_addresses
= TRUE
;
228 print_addresses
= TRUE
;
229 if (optarg
[1] != '\0')
255 if (optarg
[1] != '\0')
257 encoding
= optarg
[0];
262 print_version ("strings");
270 string_min
= optc
- '0';
272 string_min
= string_min
* 10 + optc
- '0';
299 set_default_bfd_target ();
303 datasection_only
= FALSE
;
305 SET_BINARY (fileno (stdin
));
307 print_strings ("{standard input}", stdin
, 0, 0, 0, (char *) NULL
);
312 for (; optind
< argc
; ++optind
)
314 if (strcmp (argv
[optind
], "-") == 0)
315 datasection_only
= FALSE
;
319 exit_status
|= strings_file (argv
[optind
]) == FALSE
;
327 return (exit_status
);
330 /* Scan section SECT of the file ABFD, whose printable name is in
331 ARG->filename and whose size might be in ARG->filesize. If it
332 contains initialized data set `got_a_section' and print the
335 FIXME: We ought to be able to return error codes/messages for
336 certain conditions. */
339 strings_a_section (bfd
*abfd
, asection
*sect
, void *arg
)
341 filename_and_size_t
* filename_and_sizep
;
342 bfd_size_type
*filesizep
;
343 bfd_size_type sectsize
;
346 if ((sect
->flags
& DATA_FLAGS
) != DATA_FLAGS
)
349 sectsize
= bfd_get_section_size (sect
);
354 /* Get the size of the file. This might have been cached for us. */
355 filename_and_sizep
= (filename_and_size_t
*) arg
;
356 filesizep
= & filename_and_sizep
->filesize
;
362 if (bfd_stat (abfd
, &st
))
365 /* Cache the result so that we do not repeatedly stat this file. */
366 *filesizep
= st
.st_size
;
369 /* Compare the size of the section against the size of the file.
370 If the section is bigger then the file must be corrupt and
371 we should not try dumping it. */
372 if (sectsize
>= *filesizep
)
375 mem
= xmalloc (sectsize
);
377 if (bfd_get_section_contents (abfd
, sect
, mem
, (file_ptr
) 0, sectsize
))
379 got_a_section
= TRUE
;
381 print_strings (filename_and_sizep
->filename
, NULL
, sect
->filepos
,
388 /* Scan all of the sections in FILE, and print the strings
389 in the initialized data section(s).
391 Return TRUE if successful,
392 FALSE if not (such as if FILE is not an object file). */
395 strings_object_file (const char *file
)
397 filename_and_size_t filename_and_size
;
400 abfd
= bfd_openr (file
, target
);
403 /* Treat the file as a non-object file. */
406 /* This call is mainly for its side effect of reading in the sections.
407 We follow the traditional behavior of `strings' in that we don't
408 complain if we don't recognize a file to be an object file. */
409 if (!bfd_check_format (abfd
, bfd_object
))
415 got_a_section
= FALSE
;
416 filename_and_size
.filename
= file
;
417 filename_and_size
.filesize
= 0;
418 bfd_map_over_sections (abfd
, strings_a_section
, & filename_and_size
);
420 if (!bfd_close (abfd
))
426 return got_a_section
;
429 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
432 strings_file (char *file
)
436 if (file_stat (file
, &st
) < 0)
439 non_fatal (_("'%s': No such file"), file
);
441 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
442 file
, strerror (errno
));
446 /* If we weren't told to scan the whole file,
447 try to open it as an object file and only look at
448 initialized data sections. If that fails, fall back to the
450 if (!datasection_only
|| !strings_object_file (file
))
454 stream
= file_open (file
, FOPEN_RB
);
457 fprintf (stderr
, "%s: ", program_name
);
462 print_strings (file
, stream
, (file_off
) 0, 0, 0, (char *) 0);
464 if (fclose (stream
) == EOF
)
466 fprintf (stderr
, "%s: ", program_name
);
475 /* Read the next character, return EOF if none available.
476 Assume that STREAM is positioned so that the next byte read
477 is at address ADDRESS in the file.
479 If STREAM is NULL, do not read from it.
480 The caller can supply a buffer of characters
481 to be processed before the data in STREAM.
482 MAGIC is the address of the buffer and
483 MAGICCOUNT is how many characters are in it. */
486 get_char (FILE *stream
, file_off
*address
, int *magiccount
, char **magic
)
490 unsigned char buf
[4];
492 for (i
= 0; i
< encoding_bytes
; i
++)
504 /* Only use getc_unlocked if we found a declaration for it.
505 Otherwise, libc is not thread safe by default, and we
506 should not use it. */
508 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
509 c
= getc_unlocked (stream
);
528 r
= (buf
[0] << 8) | buf
[1];
531 r
= buf
[0] | (buf
[1] << 8);
534 r
= ((long) buf
[0] << 24) | ((long) buf
[1] << 16) |
535 ((long) buf
[2] << 8) | buf
[3];
538 r
= buf
[0] | ((long) buf
[1] << 8) | ((long) buf
[2] << 16) |
539 ((long) buf
[3] << 24);
549 /* Find the strings in file FILENAME, read from STREAM.
550 Assume that STREAM is positioned so that the next byte read
551 is at address ADDRESS in the file.
552 Stop reading at address STOP_POINT in the file, if nonzero.
554 If STREAM is NULL, do not read from it.
555 The caller can supply a buffer of characters
556 to be processed before the data in STREAM.
557 MAGIC is the address of the buffer and
558 MAGICCOUNT is how many characters are in it.
559 Those characters come at address ADDRESS and the data in STREAM follow. */
562 print_strings (const char *filename
, FILE *stream
, file_off address
,
563 int stop_point
, int magiccount
, char *magic
)
565 char *buf
= (char *) xmalloc (sizeof (char) * (string_min
+ 1));
573 /* See if the next `string_min' chars are all graphic chars. */
575 if (stop_point
&& address
>= stop_point
)
578 for (i
= 0; i
< string_min
; i
++)
580 c
= get_char (stream
, &address
, &magiccount
, &magic
);
583 if (! STRING_ISGRAPHIC (c
))
584 /* Found a non-graphic. Try again starting with next char. */
589 /* We found a run of `string_min' graphic characters. Print up
590 to the next non-graphic character. */
593 printf ("%s: ", filename
);
595 switch (address_radix
)
598 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
599 if (sizeof (start
) > sizeof (long))
600 printf ("%7Lo ", (unsigned long long) start
);
603 # if !BFD_HOST_64BIT_LONG
604 if (start
!= (unsigned long) start
)
605 printf ("++%7lo ", (unsigned long) start
);
609 printf ("%7lo ", (unsigned long) start
);
613 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
614 if (sizeof (start
) > sizeof (long))
615 printf ("%7Ld ", (unsigned long long) start
);
618 # if !BFD_HOST_64BIT_LONG
619 if (start
!= (unsigned long) start
)
620 printf ("++%7ld ", (unsigned long) start
);
624 printf ("%7ld ", (long) start
);
628 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
629 if (sizeof (start
) > sizeof (long))
630 printf ("%7Lx ", (unsigned long long) start
);
633 # if !BFD_HOST_64BIT_LONG
634 if (start
!= (unsigned long) start
)
635 printf ("%lx%8.8lx ", (unsigned long) (start
>> 32),
636 (unsigned long) (start
& 0xffffffff));
640 printf ("%7lx ", (unsigned long) start
);
649 c
= get_char (stream
, &address
, &magiccount
, &magic
);
652 if (! STRING_ISGRAPHIC (c
))
661 /* Parse string S as an integer, using decimal radix by default,
662 but allowing octal and hex numbers as in C. */
665 integer_arg (char *s
)
674 else if (*++p
== 'x')
683 while (((c
= *p
++) >= '0' && c
<= '9')
684 || (radix
== 16 && (c
& ~40) >= 'A' && (c
& ~40) <= 'Z'))
687 if (c
>= '0' && c
<= '9')
690 value
+= (c
& ~40) - 'A';
701 fatal (_("invalid integer argument %s"), s
);
707 usage (FILE *stream
, int status
)
709 fprintf (stream
, _("Usage: %s [option(s)] [file(s)]\n"), program_name
);
710 fprintf (stream
, _(" Display printable strings in [file(s)] (stdin by default)\n"));
711 fprintf (stream
, _(" The options are:\n\
712 -a - --all Scan the entire file, not just the data section\n\
713 -f --print-file-name Print the name of the file before each string\n\
714 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
715 -<number> least [number] characters (default 4).\n\
716 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
717 -o An alias for --radix=o\n\
718 -T --target=<BFDNAME> Specify the binary file format\n\
719 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
720 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
721 @<file> Read options from <file>\n\
722 -h --help Display this information\n\
723 -v --version Print the program's version number\n"));
724 list_supported_targets (program_name
, stream
);
726 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);