1 /* strings -- print the strings of printable characters in files
2 Copyright (C) 1993-2021 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 /* Usage: strings [options] file...
24 - Scan each file in its entirety.
27 -d Scan only the initialized data section(s) of object files.
30 -f Print the name of the file before each string.
34 -min-len Print graphic char sequences, MIN-LEN or more bytes long,
35 that are followed by a NUL or a newline. Default is 4.
38 -t {o,x,d} Print the offset within the file before each string,
41 --include-all-whitespace
42 -w By default tab and space are the only whitepace included in graphic
43 char sequences. This option considers all of isspace() valid.
45 -o Like -to. (Some other implementations have -o like -to,
46 others like -td. We chose one arbitrarily.)
48 --encoding={s,S,b,l,B,L}
50 Select character encoding: 7-bit-character, 8-bit-character,
51 bigendian 16-bit, littleendian 16-bit, bigendian 32-bit,
56 Specify a non-default object file format.
58 --output-separator=sep_string
59 -s sep_string String used to separate parsed strings in output.
63 -h Print the usage message on the standard output.
67 -v Print the program version number.
69 Written by Richard Stallman <rms@gnu.ai.mit.edu>
70 and David MacKenzie <djm@gnu.ai.mit.edu>. */
75 #include "libiberty.h"
76 #include "safe-ctype.h"
79 #define STRING_ISGRAPHIC(c) \
82 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127) \
83 || (include_all_whitespace && ISSPACE (c))) \
90 /* The BFD section flags that identify an initialized data section. */
91 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
93 /* Radix for printing addresses (must be 8, 10 or 16). */
94 static int address_radix
;
96 /* Minimum length of sequence of graphic chars to trigger output. */
97 static int string_min
;
99 /* Whether or not we include all whitespace as a graphic char. */
100 static bool include_all_whitespace
;
102 /* TRUE means print address within file for each string. */
103 static bool print_addresses
;
105 /* TRUE means print filename for each string. */
106 static bool print_filenames
;
108 /* TRUE means for object files scan only the data section. */
109 static bool datasection_only
;
111 /* The BFD object file format. */
114 /* The character encoding format. */
115 static char encoding
;
116 static int encoding_bytes
;
118 /* Output string used to separate parsed strings */
119 static char *output_separator
;
121 static struct option long_options
[] =
123 {"all", no_argument
, NULL
, 'a'},
124 {"data", no_argument
, NULL
, 'd'},
125 {"print-file-name", no_argument
, NULL
, 'f'},
126 {"bytes", required_argument
, NULL
, 'n'},
127 {"radix", required_argument
, NULL
, 't'},
128 {"include-all-whitespace", no_argument
, NULL
, 'w'},
129 {"encoding", required_argument
, NULL
, 'e'},
130 {"target", required_argument
, NULL
, 'T'},
131 {"output-separator", required_argument
, NULL
, 's'},
132 {"help", no_argument
, NULL
, 'h'},
133 {"version", no_argument
, NULL
, 'v'},
137 static bool strings_file (char *);
138 static void print_strings (const char *, FILE *, file_ptr
, int, int, char *);
139 static void usage (FILE *, int) ATTRIBUTE_NORETURN
;
141 int main (int, char **);
144 main (int argc
, char **argv
)
148 bool files_given
= false;
152 setlocale (LC_ALL
, "");
153 bindtextdomain (PACKAGE
, LOCALEDIR
);
154 textdomain (PACKAGE
);
156 program_name
= argv
[0];
157 xmalloc_set_program_name (program_name
);
158 bfd_set_error_program_name (program_name
);
160 expandargv (&argc
, &argv
);
163 include_all_whitespace
= false;
164 print_addresses
= false;
165 print_filenames
= false;
166 if (DEFAULT_STRINGS_ALL
)
167 datasection_only
= false;
169 datasection_only
= true;
172 output_separator
= NULL
;
174 while ((optc
= getopt_long (argc
, argv
, "adfhHn:wot:e:T:s:Vv0123456789",
175 long_options
, (int *) 0)) != EOF
)
180 datasection_only
= false;
184 datasection_only
= true;
188 print_filenames
= true;
196 string_min
= (int) strtoul (optarg
, &s
, 0);
197 if (s
!= NULL
&& *s
!= 0)
198 fatal (_("invalid integer argument %s"), optarg
);
202 include_all_whitespace
= true;
206 print_addresses
= true;
211 print_addresses
= true;
212 if (optarg
[1] != '\0')
238 if (optarg
[1] != '\0')
240 encoding
= optarg
[0];
244 output_separator
= optarg
;
249 print_version ("strings");
256 numeric_opt
= optind
;
261 if (numeric_opt
!= 0)
263 string_min
= (int) strtoul (argv
[numeric_opt
- 1] + 1, &s
, 0);
264 if (s
!= NULL
&& *s
!= 0)
265 fatal (_("invalid integer argument %s"), argv
[numeric_opt
- 1] + 1);
268 fatal (_("invalid minimum string length %d"), string_min
);
288 if (bfd_init () != BFD_INIT_MAGIC
)
289 fatal (_("fatal error: libbfd ABI mismatch"));
290 set_default_bfd_target ();
294 datasection_only
= false;
295 SET_BINARY (fileno (stdin
));
296 print_strings ("{standard input}", stdin
, 0, 0, 0, (char *) NULL
);
301 for (; optind
< argc
; ++optind
)
303 if (strcmp (argv
[optind
], "-") == 0)
304 datasection_only
= false;
308 exit_status
|= !strings_file (argv
[optind
]);
316 return (exit_status
);
319 /* Scan section SECT of the file ABFD, whose printable name is
320 FILENAME. If it contains initialized data set GOT_A_SECTION and
321 print the strings in it. */
324 strings_a_section (bfd
*abfd
, asection
*sect
, const char *filename
,
327 bfd_size_type sectsize
;
330 if ((sect
->flags
& DATA_FLAGS
) != DATA_FLAGS
)
333 sectsize
= bfd_section_size (sect
);
337 if (!bfd_malloc_and_get_section (abfd
, sect
, &mem
))
339 non_fatal (_("%s: Reading section %s failed: %s"),
340 filename
, sect
->name
, bfd_errmsg (bfd_get_error ()));
344 *got_a_section
= true;
345 print_strings (filename
, NULL
, sect
->filepos
, 0, sectsize
, (char *) mem
);
349 /* Scan all of the sections in FILE, and print the strings
350 in the initialized data section(s).
352 Return TRUE if successful,
353 FALSE if not (such as if FILE is not an object file). */
356 strings_object_file (const char *file
)
362 abfd
= bfd_openr (file
, target
);
365 /* Treat the file as a non-object file. */
368 /* This call is mainly for its side effect of reading in the sections.
369 We follow the traditional behavior of `strings' in that we don't
370 complain if we don't recognize a file to be an object file. */
371 if (!bfd_check_format (abfd
, bfd_object
))
377 got_a_section
= false;
378 for (s
= abfd
->sections
; s
!= NULL
; s
= s
->next
)
379 strings_a_section (abfd
, s
, file
, &got_a_section
);
381 if (!bfd_close (abfd
))
387 return got_a_section
;
390 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
393 strings_file (char *file
)
397 /* get_file_size does not support non-S_ISREG files. */
399 if (stat (file
, &st
) < 0)
402 non_fatal (_("'%s': No such file"), file
);
404 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
405 file
, strerror (errno
));
408 else if (S_ISDIR (st
.st_mode
))
410 non_fatal (_("Warning: '%s' is a directory"), file
);
414 /* If we weren't told to scan the whole file,
415 try to open it as an object file and only look at
416 initialized data sections. If that fails, fall back to the
418 if (!datasection_only
|| !strings_object_file (file
))
422 stream
= fopen (file
, FOPEN_RB
);
425 fprintf (stderr
, "%s: ", program_name
);
430 print_strings (file
, stream
, (file_ptr
) 0, 0, 0, (char *) 0);
432 if (fclose (stream
) == EOF
)
434 fprintf (stderr
, "%s: ", program_name
);
443 /* Read the next character, return EOF if none available.
444 Assume that STREAM is positioned so that the next byte read
445 is at address ADDRESS in the file.
447 If STREAM is NULL, do not read from it.
448 The caller can supply a buffer of characters
449 to be processed before the data in STREAM.
450 MAGIC is the address of the buffer and
451 MAGICCOUNT is how many characters are in it. */
454 get_char (FILE *stream
, file_ptr
*address
, int *magiccount
, char **magic
)
459 for (i
= 0; i
< encoding_bytes
; i
++)
471 /* Only use getc_unlocked if we found a declaration for it.
472 Otherwise, libc is not thread safe by default, and we
473 should not use it. */
475 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
476 c
= getc_unlocked (stream
);
485 r
= (r
<< 8) | (c
& 0xff);
493 r
= ((r
& 0xff) << 8) | ((r
& 0xff00) >> 8);
496 r
= (((r
& 0xff) << 24) | ((r
& 0xff00) << 8)
497 | ((r
& 0xff0000) >> 8) | ((r
& 0xff000000) >> 24));
504 /* Throw away one byte of a (possibly) multi-byte char C, updating
505 address and buffer to suit. */
508 unget_part_char (long c
, file_ptr
*address
, int *magiccount
, char **magic
)
512 if (encoding_bytes
> 1)
514 *address
-= encoding_bytes
- 1;
516 if (*magiccount
== 0)
518 /* If no magic buffer exists, use temp buffer. */
528 tmp
[0] = (c
>> 8) & 0xff;
532 tmp
[0] = (c
>> 16) & 0xff;
533 tmp
[1] = (c
>> 8) & 0xff;
538 tmp
[0] = (c
>> 8) & 0xff;
539 tmp
[1] = (c
>> 16) & 0xff;
540 tmp
[2] = (c
>> 24) & 0xff;
548 /* If magic buffer exists, rewind. */
549 *magic
-= encoding_bytes
- 1;
550 *magiccount
+= encoding_bytes
- 1;
555 /* Find the strings in file FILENAME, read from STREAM.
556 Assume that STREAM is positioned so that the next byte read
557 is at address ADDRESS in the file.
558 Stop reading at address STOP_POINT in the file, if nonzero.
560 If STREAM is NULL, do not read from it.
561 The caller can supply a buffer of characters
562 to be processed before the data in STREAM.
563 MAGIC is the address of the buffer and
564 MAGICCOUNT is how many characters are in it.
565 Those characters come at address ADDRESS and the data in STREAM follow. */
568 print_strings (const char *filename
, FILE *stream
, file_ptr address
,
569 int stop_point
, int magiccount
, char *magic
)
571 char *buf
= (char *) xmalloc (sizeof (char) * (string_min
+ 1));
579 /* See if the next `string_min' chars are all graphic chars. */
581 if (stop_point
&& address
>= stop_point
)
584 for (i
= 0; i
< string_min
; i
++)
586 c
= get_char (stream
, &address
, &magiccount
, &magic
);
593 if (! STRING_ISGRAPHIC (c
))
595 /* Found a non-graphic. Try again starting with next byte. */
596 unget_part_char (c
, &address
, &magiccount
, &magic
);
602 /* We found a run of `string_min' graphic characters. Print up
603 to the next non-graphic character. */
606 printf ("%s: ", filename
);
608 switch (address_radix
)
611 if (sizeof (start
) > sizeof (long))
614 printf ("%7llo ", (unsigned long long) start
);
616 printf ("%7I64o ", (unsigned long long) start
);
620 printf ("%7lo ", (unsigned long) start
);
624 if (sizeof (start
) > sizeof (long))
627 printf ("%7llu ", (unsigned long long) start
);
629 printf ("%7I64d ", (unsigned long long) start
);
633 printf ("%7ld ", (long) start
);
637 if (sizeof (start
) > sizeof (long))
640 printf ("%7llx ", (unsigned long long) start
);
642 printf ("%7I64x ", (unsigned long long) start
);
646 printf ("%7lx ", (unsigned long) start
);
655 c
= get_char (stream
, &address
, &magiccount
, &magic
);
658 if (! STRING_ISGRAPHIC (c
))
660 unget_part_char (c
, &address
, &magiccount
, &magic
);
666 if (output_separator
)
667 fputs (output_separator
, stdout
);
675 usage (FILE *stream
, int status
)
677 fprintf (stream
, _("Usage: %s [option(s)] [file(s)]\n"), program_name
);
678 fprintf (stream
, _(" Display printable strings in [file(s)] (stdin by default)\n"));
679 fprintf (stream
, _(" The options are:\n"));
681 if (DEFAULT_STRINGS_ALL
)
682 fprintf (stream
, _("\
683 -a - --all Scan the entire file, not just the data section [default]\n\
684 -d --data Only scan the data sections in the file\n"));
686 fprintf (stream
, _("\
687 -a - --all Scan the entire file, not just the data section\n\
688 -d --data Only scan the data sections in the file [default]\n"));
690 fprintf (stream
, _("\
691 -f --print-file-name Print the name of the file before each string\n\
692 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
693 -<number> least [number] characters (default 4).\n\
694 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
695 -w --include-all-whitespace Include all whitespace as valid string characters\n\
696 -o An alias for --radix=o\n\
697 -T --target=<BFDNAME> Specify the binary file format\n\
698 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
699 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
700 -s --output-separator=<string> String used to separate strings in output.\n\
701 @<file> Read options from <file>\n\
702 -h --help Display this information\n\
703 -v -V --version Print the program's version number\n"));
704 list_supported_targets (program_name
, stream
);
705 if (REPORT_BUGS_TO
[0] && status
== 0)
706 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);