Release 2.33.1
[external/binutils.git] / binutils / strings.c
1 /* strings -- print the strings of printable characters in files
2    Copyright (C) 1993-2019 Free Software Foundation, Inc.
3
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)
7    any later version.
8
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.
13
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
17    02110-1301, USA.  */
18 \f
19 /* Usage: strings [options] file...
20
21    Options:
22    --all
23    -a
24    -            Scan each file in its entirety.
25
26    --data
27    -d           Scan only the initialized data section(s) of object files.
28
29    --print-file-name
30    -f           Print the name of the file before each string.
31
32    --bytes=min-len
33    -n min-len
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.
36
37    --radix={o,x,d}
38    -t {o,x,d}   Print the offset within the file before each string,
39                 in octal/hex/decimal.
40
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.
44
45    -o           Like -to.  (Some other implementations have -o like -to,
46                 others like -td.  We chose one arbitrarily.)
47
48    --encoding={s,S,b,l,B,L}
49    -e {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,
52                 littleendian 32-bit.
53
54    --target=BFDNAME
55    -T {bfdname}
56                 Specify a non-default object file format.
57
58   --output-separator=sep_string
59   -s sep_string String used to separate parsed strings in output.
60                 Default is newline.
61
62    --help
63    -h           Print the usage message on the standard output.
64
65    --version
66    -V
67    -v           Print the program version number.
68
69    Written by Richard Stallman <rms@gnu.ai.mit.edu>
70    and David MacKenzie <djm@gnu.ai.mit.edu>.  */
71
72 #include "sysdep.h"
73 #include "bfd.h"
74 #include "getopt.h"
75 #include "libiberty.h"
76 #include "safe-ctype.h"
77 #include "bucomm.h"
78
79 #define STRING_ISGRAPHIC(c) \
80       (   (c) >= 0 \
81        && (c) <= 255 \
82        && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127) \
83            || (include_all_whitespace && ISSPACE (c))) \
84       )
85
86 #ifndef errno
87 extern int errno;
88 #endif
89
90 /* The BFD section flags that identify an initialized data section.  */
91 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
92
93 /* Radix for printing addresses (must be 8, 10 or 16).  */
94 static int address_radix;
95
96 /* Minimum length of sequence of graphic chars to trigger output.  */
97 static int string_min;
98
99 /* Whether or not we include all whitespace as a graphic char.   */
100 static bfd_boolean include_all_whitespace;
101
102 /* TRUE means print address within file for each string.  */
103 static bfd_boolean print_addresses;
104
105 /* TRUE means print filename for each string.  */
106 static bfd_boolean print_filenames;
107
108 /* TRUE means for object files scan only the data section.  */
109 static bfd_boolean datasection_only;
110
111 /* The BFD object file format.  */
112 static char *target;
113
114 /* The character encoding format.  */
115 static char encoding;
116 static int encoding_bytes;
117
118 /* Output string used to separate parsed strings  */
119 static char *output_separator;
120
121 static struct option long_options[] =
122 {
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'},
134   {NULL, 0, NULL, 0}
135 };
136
137 static bfd_boolean strings_file (char *);
138 static void print_strings (const char *, FILE *, file_ptr, int, int, char *);
139 static void usage (FILE *, int) ATTRIBUTE_NORETURN;
140 \f
141 int main (int, char **);
142
143 int
144 main (int argc, char **argv)
145 {
146   int optc;
147   int exit_status = 0;
148   bfd_boolean files_given = FALSE;
149   char *s;
150   int numeric_opt = 0;
151
152 #if defined (HAVE_SETLOCALE)
153   setlocale (LC_ALL, "");
154 #endif
155   bindtextdomain (PACKAGE, LOCALEDIR);
156   textdomain (PACKAGE);
157
158   program_name = argv[0];
159   xmalloc_set_program_name (program_name);
160   bfd_set_error_program_name (program_name);
161
162   expandargv (&argc, &argv);
163
164   string_min = 4;
165   include_all_whitespace = FALSE;
166   print_addresses = FALSE;
167   print_filenames = FALSE;
168   if (DEFAULT_STRINGS_ALL)
169     datasection_only = FALSE;
170   else
171     datasection_only = TRUE;
172   target = NULL;
173   encoding = 's';
174   output_separator = NULL;
175
176   while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:Vv0123456789",
177                               long_options, (int *) 0)) != EOF)
178     {
179       switch (optc)
180         {
181         case 'a':
182           datasection_only = FALSE;
183           break;
184
185         case 'd':
186           datasection_only = TRUE;
187           break;
188
189         case 'f':
190           print_filenames = TRUE;
191           break;
192
193         case 'H':
194         case 'h':
195           usage (stdout, 0);
196
197         case 'n':
198           string_min = (int) strtoul (optarg, &s, 0);
199           if (s != NULL && *s != 0)
200             fatal (_("invalid integer argument %s"), optarg);
201           break;
202
203         case 'w':
204           include_all_whitespace = TRUE;
205           break;
206
207         case 'o':
208           print_addresses = TRUE;
209           address_radix = 8;
210           break;
211
212         case 't':
213           print_addresses = TRUE;
214           if (optarg[1] != '\0')
215             usage (stderr, 1);
216           switch (optarg[0])
217             {
218             case 'o':
219               address_radix = 8;
220               break;
221
222             case 'd':
223               address_radix = 10;
224               break;
225
226             case 'x':
227               address_radix = 16;
228               break;
229
230             default:
231               usage (stderr, 1);
232             }
233           break;
234
235         case 'T':
236           target = optarg;
237           break;
238
239         case 'e':
240           if (optarg[1] != '\0')
241             usage (stderr, 1);
242           encoding = optarg[0];
243           break;
244
245         case 's':
246           output_separator = optarg;
247           break;
248
249         case 'V':
250         case 'v':
251           print_version ("strings");
252           break;
253
254         case '?':
255           usage (stderr, 1);
256
257         default:
258           numeric_opt = optind;
259           break;
260         }
261     }
262
263   if (numeric_opt != 0)
264     {
265       string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0);
266       if (s != NULL && *s != 0)
267         fatal (_("invalid integer argument %s"), argv[numeric_opt - 1] + 1);
268     }
269   if (string_min < 1)
270     fatal (_("invalid minimum string length %d"), string_min);
271
272   switch (encoding)
273     {
274     case 'S':
275     case 's':
276       encoding_bytes = 1;
277       break;
278     case 'b':
279     case 'l':
280       encoding_bytes = 2;
281       break;
282     case 'B':
283     case 'L':
284       encoding_bytes = 4;
285       break;
286     default:
287       usage (stderr, 1);
288     }
289
290   if (bfd_init () != BFD_INIT_MAGIC)
291     fatal (_("fatal error: libbfd ABI mismatch"));
292   set_default_bfd_target ();
293
294   if (optind >= argc)
295     {
296       datasection_only = FALSE;
297       SET_BINARY (fileno (stdin));
298       print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
299       files_given = TRUE;
300     }
301   else
302     {
303       for (; optind < argc; ++optind)
304         {
305           if (strcmp (argv[optind], "-") == 0)
306             datasection_only = FALSE;
307           else
308             {
309               files_given = TRUE;
310               exit_status |= !strings_file (argv[optind]);
311             }
312         }
313     }
314
315   if (!files_given)
316     usage (stderr, 1);
317
318   return (exit_status);
319 }
320 \f
321 /* Scan section SECT of the file ABFD, whose printable name is
322    FILENAME.  If it contains initialized data set GOT_A_SECTION and
323    print the strings in it.  */
324
325 static void
326 strings_a_section (bfd *abfd, asection *sect, const char *filename,
327                    bfd_boolean *got_a_section)
328 {
329   bfd_size_type sectsize;
330   bfd_byte *mem;
331
332   if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
333     return;
334
335   sectsize = bfd_get_section_size (sect);
336   if (sectsize == 0)
337     return;
338
339   if (!bfd_malloc_and_get_section (abfd, sect, &mem))
340     {
341       non_fatal (_("%s: Reading section %s failed: %s"),
342                  filename, sect->name, bfd_errmsg (bfd_get_error ()));
343       return;
344     }
345
346   *got_a_section = TRUE;
347   print_strings (filename, NULL, sect->filepos, 0, sectsize, (char *) mem);
348   free (mem);
349 }
350
351 /* Scan all of the sections in FILE, and print the strings
352    in the initialized data section(s).
353
354    Return TRUE if successful,
355    FALSE if not (such as if FILE is not an object file).  */
356
357 static bfd_boolean
358 strings_object_file (const char *file)
359 {
360   bfd *abfd;
361   asection *s;
362   bfd_boolean got_a_section;
363
364   abfd = bfd_openr (file, target);
365
366   if (abfd == NULL)
367     /* Treat the file as a non-object file.  */
368     return FALSE;
369
370   /* This call is mainly for its side effect of reading in the sections.
371      We follow the traditional behavior of `strings' in that we don't
372      complain if we don't recognize a file to be an object file.  */
373   if (!bfd_check_format (abfd, bfd_object))
374     {
375       bfd_close (abfd);
376       return FALSE;
377     }
378
379   got_a_section = FALSE;
380   for (s = abfd->sections; s != NULL; s = s->next)
381     strings_a_section (abfd, s, file, &got_a_section);
382
383   if (!bfd_close (abfd))
384     {
385       bfd_nonfatal (file);
386       return FALSE;
387     }
388
389   return got_a_section;
390 }
391
392 /* Print the strings in FILE.  Return TRUE if ok, FALSE if an error occurs.  */
393
394 static bfd_boolean
395 strings_file (char *file)
396 {
397   struct stat st;
398
399   /* get_file_size does not support non-S_ISREG files.  */
400
401   if (stat (file, &st) < 0)
402     {
403       if (errno == ENOENT)
404         non_fatal (_("'%s': No such file"), file);
405       else
406         non_fatal (_("Warning: could not locate '%s'.  reason: %s"),
407                    file, strerror (errno));
408       return FALSE;
409     }
410   else if (S_ISDIR (st.st_mode))
411     {
412       non_fatal (_("Warning: '%s' is a directory"), file);
413       return FALSE;
414     }
415
416   /* If we weren't told to scan the whole file,
417      try to open it as an object file and only look at
418      initialized data sections.  If that fails, fall back to the
419      whole file.  */
420   if (!datasection_only || !strings_object_file (file))
421     {
422       FILE *stream;
423
424       stream = fopen (file, FOPEN_RB);
425       if (stream == NULL)
426         {
427           fprintf (stderr, "%s: ", program_name);
428           perror (file);
429           return FALSE;
430         }
431
432       print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
433
434       if (fclose (stream) == EOF)
435         {
436           fprintf (stderr, "%s: ", program_name);
437           perror (file);
438           return FALSE;
439         }
440     }
441
442   return TRUE;
443 }
444 \f
445 /* Read the next character, return EOF if none available.
446    Assume that STREAM is positioned so that the next byte read
447    is at address ADDRESS in the file.
448
449    If STREAM is NULL, do not read from it.
450    The caller can supply a buffer of characters
451    to be processed before the data in STREAM.
452    MAGIC is the address of the buffer and
453    MAGICCOUNT is how many characters are in it.  */
454
455 static long
456 get_char (FILE *stream, file_ptr *address, int *magiccount, char **magic)
457 {
458   int c, i;
459   long r = 0;
460
461   for (i = 0; i < encoding_bytes; i++)
462     {
463       if (*magiccount)
464         {
465           (*magiccount)--;
466           c = *(*magic)++;
467         }
468       else
469         {
470           if (stream == NULL)
471             return EOF;
472
473           /* Only use getc_unlocked if we found a declaration for it.
474              Otherwise, libc is not thread safe by default, and we
475              should not use it.  */
476
477 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
478           c = getc_unlocked (stream);
479 #else
480           c = getc (stream);
481 #endif
482           if (c == EOF)
483             return EOF;
484         }
485
486       (*address)++;
487       r = (r << 8) | (c & 0xff);
488     }
489
490   switch (encoding)
491     {
492     default:
493       break;
494     case 'l':
495       r = ((r & 0xff) << 8) | ((r & 0xff00) >> 8);
496       break;
497     case 'L':
498       r = (((r & 0xff) << 24) | ((r & 0xff00) << 8)
499            | ((r & 0xff0000) >> 8) | ((r & 0xff000000) >> 24));
500       break;
501     }
502
503   return r;
504 }
505
506 /* Throw away one byte of a (possibly) multi-byte char C, updating
507    address and buffer to suit.  */
508
509 static void
510 unget_part_char (long c, file_ptr *address, int *magiccount, char **magic)
511 {
512   static char tmp[4];
513
514   if (encoding_bytes > 1)
515     {
516       *address -= encoding_bytes - 1;
517
518       if (*magiccount == 0)
519         {
520           /* If no magic buffer exists, use temp buffer.  */
521           switch (encoding)
522             {
523             default:
524               break;
525             case 'b':
526               tmp[0] = c & 0xff;
527               *magiccount = 1;
528               break;
529             case 'l':
530               tmp[0] = (c >> 8) & 0xff;
531               *magiccount = 1;
532               break;
533             case 'B':
534               tmp[0] = (c >> 16) & 0xff;
535               tmp[1] = (c >> 8) & 0xff;
536               tmp[2] = c & 0xff;
537               *magiccount = 3;
538               break;
539             case 'L':
540               tmp[0] = (c >> 8) & 0xff;
541               tmp[1] = (c >> 16) & 0xff;
542               tmp[2] = (c >> 24) & 0xff;
543               *magiccount = 3;
544               break;
545             }
546           *magic = tmp;
547         }
548       else
549         {
550           /* If magic buffer exists, rewind.  */
551           *magic -= encoding_bytes - 1;
552           *magiccount += encoding_bytes - 1;
553         }
554     }
555 }
556 \f
557 /* Find the strings in file FILENAME, read from STREAM.
558    Assume that STREAM is positioned so that the next byte read
559    is at address ADDRESS in the file.
560    Stop reading at address STOP_POINT in the file, if nonzero.
561
562    If STREAM is NULL, do not read from it.
563    The caller can supply a buffer of characters
564    to be processed before the data in STREAM.
565    MAGIC is the address of the buffer and
566    MAGICCOUNT is how many characters are in it.
567    Those characters come at address ADDRESS and the data in STREAM follow.  */
568
569 static void
570 print_strings (const char *filename, FILE *stream, file_ptr address,
571                int stop_point, int magiccount, char *magic)
572 {
573   char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
574
575   while (1)
576     {
577       file_ptr start;
578       int i;
579       long c;
580
581       /* See if the next `string_min' chars are all graphic chars.  */
582     tryline:
583       if (stop_point && address >= stop_point)
584         break;
585       start = address;
586       for (i = 0; i < string_min; i++)
587         {
588           c = get_char (stream, &address, &magiccount, &magic);
589           if (c == EOF)
590             {
591               free (buf);
592               return;
593             }
594
595           if (! STRING_ISGRAPHIC (c))
596             {
597               /* Found a non-graphic.  Try again starting with next byte.  */
598               unget_part_char (c, &address, &magiccount, &magic);
599               goto tryline;
600             }
601           buf[i] = c;
602         }
603
604       /* We found a run of `string_min' graphic characters.  Print up
605          to the next non-graphic character.  */
606
607       if (print_filenames)
608         printf ("%s: ", filename);
609       if (print_addresses)
610         switch (address_radix)
611           {
612           case 8:
613 #ifdef HAVE_LONG_LONG
614             if (sizeof (start) > sizeof (long))
615               {
616 # ifndef __MSVCRT__
617                 printf ("%7llo ", (unsigned long long) start);
618 # else
619                 printf ("%7I64o ", (unsigned long long) start);
620 # endif
621               }
622             else
623 #elif !BFD_HOST_64BIT_LONG
624               if (start != (unsigned long) start)
625                 printf ("++%7lo ", (unsigned long) start);
626               else
627 #endif
628                 printf ("%7lo ", (unsigned long) start);
629             break;
630
631           case 10:
632 #ifdef HAVE_LONG_LONG
633             if (sizeof (start) > sizeof (long))
634               {
635 # ifndef __MSVCRT__
636                 printf ("%7llu ", (unsigned long long) start);
637 # else
638                 printf ("%7I64d ", (unsigned long long) start);
639 # endif
640               }
641             else
642 #elif !BFD_HOST_64BIT_LONG
643               if (start != (unsigned long) start)
644                 printf ("++%7lu ", (unsigned long) start);
645               else
646 #endif
647                 printf ("%7ld ", (long) start);
648             break;
649
650           case 16:
651 #ifdef HAVE_LONG_LONG
652             if (sizeof (start) > sizeof (long))
653               {
654 # ifndef __MSVCRT__
655                 printf ("%7llx ", (unsigned long long) start);
656 # else
657                 printf ("%7I64x ", (unsigned long long) start);
658 # endif
659               }
660             else
661 #elif !BFD_HOST_64BIT_LONG
662               if (start != (unsigned long) start)
663                 printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
664                         (unsigned long) (start & 0xffffffff));
665               else
666 #endif
667                 printf ("%7lx ", (unsigned long) start);
668             break;
669           }
670
671       buf[i] = '\0';
672       fputs (buf, stdout);
673
674       while (1)
675         {
676           c = get_char (stream, &address, &magiccount, &magic);
677           if (c == EOF)
678             break;
679           if (! STRING_ISGRAPHIC (c))
680             {
681               unget_part_char (c, &address, &magiccount, &magic);
682               break;
683             }
684           putchar (c);
685         }
686
687       if (output_separator)
688         fputs (output_separator, stdout);
689       else
690         putchar ('\n');
691     }
692   free (buf);
693 }
694 \f
695 static void
696 usage (FILE *stream, int status)
697 {
698   fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
699   fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
700   fprintf (stream, _(" The options are:\n"));
701
702   if (DEFAULT_STRINGS_ALL)
703     fprintf (stream, _("\
704   -a - --all                Scan the entire file, not just the data section [default]\n\
705   -d --data                 Only scan the data sections in the file\n"));
706   else
707     fprintf (stream, _("\
708   -a - --all                Scan the entire file, not just the data section\n\
709   -d --data                 Only scan the data sections in the file [default]\n"));
710
711   fprintf (stream, _("\
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   -w --include-all-whitespace Include all whitespace as valid string characters\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   -s --output-separator=<string> String used to separate strings in output.\n\
722   @<file>                   Read options from <file>\n\
723   -h --help                 Display this information\n\
724   -v -V --version           Print the program's version number\n"));
725   list_supported_targets (program_name, stream);
726   if (REPORT_BUGS_TO[0] && status == 0)
727     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
728   exit (status);
729 }