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
;
163 #if defined (HAVE_SETLOCALE)
164 setlocale (LC_ALL
, "");
166 bindtextdomain (PACKAGE
, LOCALEDIR
);
167 textdomain (PACKAGE
);
169 program_name
= argv
[0];
170 xmalloc_set_program_name (program_name
);
172 expandargv (&argc
, &argv
);
175 print_addresses
= FALSE
;
176 print_filenames
= FALSE
;
177 datasection_only
= TRUE
;
181 while ((optc
= getopt_long (argc
, argv
, "afhHn:ot:e:T:Vv0123456789",
182 long_options
, (int *) 0)) != EOF
)
187 datasection_only
= FALSE
;
191 print_filenames
= TRUE
;
199 string_min
= (int) strtoul (optarg
, &s
, 0);
200 if (s
!= NULL
&& *s
!= 0)
201 fatal (_("invalid integer argument %s"), optarg
);
205 print_addresses
= TRUE
;
210 print_addresses
= TRUE
;
211 if (optarg
[1] != '\0')
237 if (optarg
[1] != '\0')
239 encoding
= optarg
[0];
244 print_version ("strings");
251 numeric_opt
= optind
;
256 if (numeric_opt
!= 0)
258 string_min
= (int) strtoul (argv
[numeric_opt
- 1] + 1, &s
, 0);
259 if (s
!= NULL
&& *s
!= 0)
260 fatal (_("invalid integer argument %s"), argv
[numeric_opt
- 1] + 1);
263 fatal (_("invalid minimum string length %d"), string_min
);
284 set_default_bfd_target ();
288 datasection_only
= FALSE
;
289 SET_BINARY (fileno (stdin
));
290 print_strings ("{standard input}", stdin
, 0, 0, 0, (char *) NULL
);
295 for (; optind
< argc
; ++optind
)
297 if (strcmp (argv
[optind
], "-") == 0)
298 datasection_only
= FALSE
;
302 exit_status
|= strings_file (argv
[optind
]) == FALSE
;
310 return (exit_status
);
313 /* Scan section SECT of the file ABFD, whose printable name is in
314 ARG->filename and whose size might be in ARG->filesize. If it
315 contains initialized data set `got_a_section' and print the
318 FIXME: We ought to be able to return error codes/messages for
319 certain conditions. */
322 strings_a_section (bfd
*abfd
, asection
*sect
, void *arg
)
324 filename_and_size_t
* filename_and_sizep
;
325 bfd_size_type
*filesizep
;
326 bfd_size_type sectsize
;
329 if ((sect
->flags
& DATA_FLAGS
) != DATA_FLAGS
)
332 sectsize
= bfd_get_section_size (sect
);
337 /* Get the size of the file. This might have been cached for us. */
338 filename_and_sizep
= (filename_and_size_t
*) arg
;
339 filesizep
= & filename_and_sizep
->filesize
;
345 if (bfd_stat (abfd
, &st
))
348 /* Cache the result so that we do not repeatedly stat this file. */
349 *filesizep
= st
.st_size
;
352 /* Compare the size of the section against the size of the file.
353 If the section is bigger then the file must be corrupt and
354 we should not try dumping it. */
355 if (sectsize
>= *filesizep
)
358 mem
= xmalloc (sectsize
);
360 if (bfd_get_section_contents (abfd
, sect
, mem
, (file_ptr
) 0, sectsize
))
362 got_a_section
= TRUE
;
364 print_strings (filename_and_sizep
->filename
, NULL
, sect
->filepos
,
371 /* Scan all of the sections in FILE, and print the strings
372 in the initialized data section(s).
374 Return TRUE if successful,
375 FALSE if not (such as if FILE is not an object file). */
378 strings_object_file (const char *file
)
380 filename_and_size_t filename_and_size
;
383 abfd
= bfd_openr (file
, target
);
386 /* Treat the file as a non-object file. */
389 /* This call is mainly for its side effect of reading in the sections.
390 We follow the traditional behavior of `strings' in that we don't
391 complain if we don't recognize a file to be an object file. */
392 if (!bfd_check_format (abfd
, bfd_object
))
398 got_a_section
= FALSE
;
399 filename_and_size
.filename
= file
;
400 filename_and_size
.filesize
= 0;
401 bfd_map_over_sections (abfd
, strings_a_section
, & filename_and_size
);
403 if (!bfd_close (abfd
))
409 return got_a_section
;
412 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
415 strings_file (char *file
)
419 if (file_stat (file
, &st
) < 0)
422 non_fatal (_("'%s': No such file"), file
);
424 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
425 file
, strerror (errno
));
429 /* If we weren't told to scan the whole file,
430 try to open it as an object file and only look at
431 initialized data sections. If that fails, fall back to the
433 if (!datasection_only
|| !strings_object_file (file
))
437 stream
= file_open (file
, FOPEN_RB
);
440 fprintf (stderr
, "%s: ", program_name
);
445 print_strings (file
, stream
, (file_off
) 0, 0, 0, (char *) 0);
447 if (fclose (stream
) == EOF
)
449 fprintf (stderr
, "%s: ", program_name
);
458 /* Read the next character, return EOF if none available.
459 Assume that STREAM is positioned so that the next byte read
460 is at address ADDRESS in the file.
462 If STREAM is NULL, do not read from it.
463 The caller can supply a buffer of characters
464 to be processed before the data in STREAM.
465 MAGIC is the address of the buffer and
466 MAGICCOUNT is how many characters are in it. */
469 get_char (FILE *stream
, file_off
*address
, int *magiccount
, char **magic
)
473 unsigned char buf
[4];
475 for (i
= 0; i
< encoding_bytes
; i
++)
487 /* Only use getc_unlocked if we found a declaration for it.
488 Otherwise, libc is not thread safe by default, and we
489 should not use it. */
491 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
492 c
= getc_unlocked (stream
);
511 r
= (buf
[0] << 8) | buf
[1];
514 r
= buf
[0] | (buf
[1] << 8);
517 r
= ((long) buf
[0] << 24) | ((long) buf
[1] << 16) |
518 ((long) buf
[2] << 8) | buf
[3];
521 r
= buf
[0] | ((long) buf
[1] << 8) | ((long) buf
[2] << 16) |
522 ((long) buf
[3] << 24);
532 /* Find the strings in file FILENAME, read from STREAM.
533 Assume that STREAM is positioned so that the next byte read
534 is at address ADDRESS in the file.
535 Stop reading at address STOP_POINT in the file, if nonzero.
537 If STREAM is NULL, do not read from it.
538 The caller can supply a buffer of characters
539 to be processed before the data in STREAM.
540 MAGIC is the address of the buffer and
541 MAGICCOUNT is how many characters are in it.
542 Those characters come at address ADDRESS and the data in STREAM follow. */
545 print_strings (const char *filename
, FILE *stream
, file_off address
,
546 int stop_point
, int magiccount
, char *magic
)
548 char *buf
= (char *) xmalloc (sizeof (char) * (string_min
+ 1));
556 /* See if the next `string_min' chars are all graphic chars. */
558 if (stop_point
&& address
>= stop_point
)
561 for (i
= 0; i
< string_min
; i
++)
563 c
= get_char (stream
, &address
, &magiccount
, &magic
);
566 if (! STRING_ISGRAPHIC (c
))
567 /* Found a non-graphic. Try again starting with next char. */
572 /* We found a run of `string_min' graphic characters. Print up
573 to the next non-graphic character. */
576 printf ("%s: ", filename
);
578 switch (address_radix
)
581 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
582 if (sizeof (start
) > sizeof (long))
585 printf ("%7llo ", (unsigned long long) start
);
587 printf ("%7I64o ", (unsigned long long) start
);
591 #elif !BFD_HOST_64BIT_LONG
592 if (start
!= (unsigned long) start
)
593 printf ("++%7lo ", (unsigned long) start
);
596 printf ("%7lo ", (unsigned long) start
);
600 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
601 if (sizeof (start
) > sizeof (long))
604 printf ("%7lld ", (unsigned long long) start
);
606 printf ("%7I64d ", (unsigned long long) start
);
610 #elif !BFD_HOST_64BIT_LONG
611 if (start
!= (unsigned long) start
)
612 printf ("++%7ld ", (unsigned long) start
);
615 printf ("%7ld ", (long) start
);
619 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
620 if (sizeof (start
) > sizeof (long))
623 printf ("%7llx ", (unsigned long long) start
);
625 printf ("%7I64x ", (unsigned long long) start
);
629 #elif !BFD_HOST_64BIT_LONG
630 if (start
!= (unsigned long) start
)
631 printf ("%lx%8.8lx ", (unsigned long) (start
>> 32),
632 (unsigned long) (start
& 0xffffffff));
635 printf ("%7lx ", (unsigned long) start
);
644 c
= get_char (stream
, &address
, &magiccount
, &magic
);
647 if (! STRING_ISGRAPHIC (c
))
657 usage (FILE *stream
, int status
)
659 fprintf (stream
, _("Usage: %s [option(s)] [file(s)]\n"), program_name
);
660 fprintf (stream
, _(" Display printable strings in [file(s)] (stdin by default)\n"));
661 fprintf (stream
, _(" The options are:\n\
662 -a - --all Scan the entire file, not just the data section\n\
663 -f --print-file-name Print the name of the file before each string\n\
664 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
665 -<number> least [number] characters (default 4).\n\
666 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
667 -o An alias for --radix=o\n\
668 -T --target=<BFDNAME> Specify the binary file format\n\
669 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
670 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
671 @<file> Read options from <file>\n\
672 -h --help Display this information\n\
673 -v -V --version Print the program's version number\n"));
674 list_supported_targets (program_name
, stream
);
675 if (REPORT_BUGS_TO
[0] && status
== 0)
676 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);