1 /* strings -- print the strings of printable characters in files
2    Copyright (C) 1993-2016 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 
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 == TRUE && 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 /* TRUE if we found an initialized data section in the current file.  */
112 static bfd_boolean got_a_section;
113 
114 /* The BFD object file format.  */
115 static char *target;
116 
117 /* The character encoding format.  */
118 static char encoding;
119 static int encoding_bytes;
120 
121 /* Output string used to separate parsed strings  */
122 static char *output_separator;
123 
124 static struct option long_options[] =
125 {
126   {"all", no_argument, NULL, 'a'},
127   {"data", no_argument, NULL, 'd'},
128   {"print-file-name", no_argument, NULL, 'f'},
129   {"bytes", required_argument, NULL, 'n'},
130   {"radix", required_argument, NULL, 't'},
131   {"include-all-whitespace", required_argument, NULL, 'w'},
132   {"encoding", required_argument, NULL, 'e'},
133   {"target", required_argument, NULL, 'T'},
134   {"output-separator", required_argument, NULL, 's'},
135   {"help", no_argument, NULL, 'h'},
136   {"version", no_argument, NULL, 'v'},
137   {NULL, 0, NULL, 0}
138 };
139 
140 /* Records the size of a named file so that we
141    do not repeatedly run bfd_stat() on it.  */
142 
143 typedef struct
144 {
145   const char *  filename;
146   bfd_size_type filesize;
147 } filename_and_size_t;
148 
149 static void strings_a_section (bfd *, asection *, void *);
150 static bfd_boolean strings_object_file (const char *);
151 static bfd_boolean strings_file (char *);
152 static void print_strings (const char *, FILE *, file_ptr, int, int, char *);
153 static void usage (FILE *, int);
154 static long get_char (FILE *, file_ptr *, int *, char **);
155 
156 int main (int, char **);
157 
158 int
159 main (int argc, char **argv)
160 {
161   int optc;
162   int exit_status = 0;
163   bfd_boolean files_given = FALSE;
164   char *s;
165   int numeric_opt = 0;
166 
167 #if defined (HAVE_SETLOCALE)
168   setlocale (LC_ALL, "");
169 #endif
170   bindtextdomain (PACKAGE, LOCALEDIR);
171   textdomain (PACKAGE);
172 
173   program_name = argv[0];
174   xmalloc_set_program_name (program_name);
175   bfd_set_error_program_name (program_name);
176 
177   expandargv (&argc, &argv);
178 
179   string_min = 4;
180   include_all_whitespace = FALSE;
181   print_addresses = FALSE;
182   print_filenames = FALSE;
183   if (DEFAULT_STRINGS_ALL)
184     datasection_only = FALSE;
185   else
186     datasection_only = TRUE;
187   target = NULL;
188   encoding = 's';
189   output_separator = NULL;
190 
191   while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:Vv0123456789",
192 			      long_options, (int *) 0)) != EOF)
193     {
194       switch (optc)
195 	{
196 	case 'a':
197 	  datasection_only = FALSE;
198 	  break;
199 
200 	case 'd':
201 	  datasection_only = TRUE;
202 	  break;
203 
204 	case 'f':
205 	  print_filenames = TRUE;
206 	  break;
207 
208 	case 'H':
209 	case 'h':
210 	  usage (stdout, 0);
211 
212 	case 'n':
213 	  string_min = (int) strtoul (optarg, &s, 0);
214 	  if (s != NULL && *s != 0)
215 	    fatal (_("invalid integer argument %s"), optarg);
216 	  break;
217 
218 	case 'w':
219 	  include_all_whitespace = TRUE;
220 	  break;
221 
222 	case 'o':
223 	  print_addresses = TRUE;
224 	  address_radix = 8;
225 	  break;
226 
227 	case 't':
228 	  print_addresses = TRUE;
229 	  if (optarg[1] != '\0')
230 	    usage (stderr, 1);
231 	  switch (optarg[0])
232 	    {
233 	    case 'o':
234 	      address_radix = 8;
235 	      break;
236 
237 	    case 'd':
238 	      address_radix = 10;
239 	      break;
240 
241 	    case 'x':
242 	      address_radix = 16;
243 	      break;
244 
245 	    default:
246 	      usage (stderr, 1);
247 	    }
248 	  break;
249 
250 	case 'T':
251 	  target = optarg;
252 	  break;
253 
254 	case 'e':
255 	  if (optarg[1] != '\0')
256 	    usage (stderr, 1);
257 	  encoding = optarg[0];
258 	  break;
259 
260 	case 's':
261 	  output_separator = optarg;
262           break;
263 
264 	case 'V':
265 	case 'v':
266 	  print_version ("strings");
267 	  break;
268 
269 	case '?':
270 	  usage (stderr, 1);
271 
272 	default:
273 	  numeric_opt = optind;
274 	  break;
275 	}
276     }
277 
278   if (numeric_opt != 0)
279     {
280       string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0);
281       if (s != NULL && *s != 0)
282 	fatal (_("invalid integer argument %s"), argv[numeric_opt - 1] + 1);
283     }
284   if (string_min < 1)
285     fatal (_("invalid minimum string length %d"), string_min);
286 
287   switch (encoding)
288     {
289     case 'S':
290     case 's':
291       encoding_bytes = 1;
292       break;
293     case 'b':
294     case 'l':
295       encoding_bytes = 2;
296       break;
297     case 'B':
298     case 'L':
299       encoding_bytes = 4;
300       break;
301     default:
302       usage (stderr, 1);
303     }
304 
305   bfd_init ();
306   set_default_bfd_target ();
307 
308   if (optind >= argc)
309     {
310       datasection_only = FALSE;
311       SET_BINARY (fileno (stdin));
312       print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
313       files_given = TRUE;
314     }
315   else
316     {
317       for (; optind < argc; ++optind)
318 	{
319 	  if (strcmp (argv[optind], "-") == 0)
320 	    datasection_only = FALSE;
321 	  else
322 	    {
323 	      files_given = TRUE;
324 	      exit_status |= strings_file (argv[optind]) == FALSE;
325 	    }
326 	}
327     }
328 
329   if (!files_given)
330     usage (stderr, 1);
331 
332   return (exit_status);
333 }
334 
335 /* Scan section SECT of the file ABFD, whose printable name is in
336    ARG->filename and whose size might be in ARG->filesize.  If it
337    contains initialized data set `got_a_section' and print the
338    strings in it.
339 
340    FIXME: We ought to be able to return error codes/messages for
341    certain conditions.  */
342 
343 static void
344 strings_a_section (bfd *abfd, asection *sect, void *arg)
345 {
346   filename_and_size_t * filename_and_sizep;
347   bfd_size_type *filesizep;
348   bfd_size_type sectsize;
349   void *mem;
350 
351   if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
352     return;
353 
354   sectsize = bfd_get_section_size (sect);
355 
356   if (sectsize <= 0)
357     return;
358 
359   /* Get the size of the file.  This might have been cached for us.  */
360   filename_and_sizep = (filename_and_size_t *) arg;
361   filesizep = & filename_and_sizep->filesize;
362 
363   if (*filesizep == 0)
364     {
365       struct stat st;
366 
367       if (bfd_stat (abfd, &st))
368 	return;
369 
370       /* Cache the result so that we do not repeatedly stat this file.  */
371       *filesizep = st.st_size;
372     }
373 
374   /* Compare the size of the section against the size of the file.
375      If the section is bigger then the file must be corrupt and
376      we should not try dumping it.  */
377   if (sectsize >= *filesizep)
378     return;
379 
380   mem = xmalloc (sectsize);
381 
382   if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
383     {
384       got_a_section = TRUE;
385 
386       print_strings (filename_and_sizep->filename, NULL, sect->filepos,
387 		     0, sectsize, (char *) mem);
388     }
389 
390   free (mem);
391 }
392 
393 /* Scan all of the sections in FILE, and print the strings
394    in the initialized data section(s).
395 
396    Return TRUE if successful,
397    FALSE if not (such as if FILE is not an object file).  */
398 
399 static bfd_boolean
400 strings_object_file (const char *file)
401 {
402   filename_and_size_t filename_and_size;
403   bfd *abfd;
404 
405   abfd = bfd_openr (file, target);
406 
407   if (abfd == NULL)
408     /* Treat the file as a non-object file.  */
409     return FALSE;
410 
411   /* This call is mainly for its side effect of reading in the sections.
412      We follow the traditional behavior of `strings' in that we don't
413      complain if we don't recognize a file to be an object file.  */
414   if (!bfd_check_format (abfd, bfd_object))
415     {
416       bfd_close (abfd);
417       return FALSE;
418     }
419 
420   got_a_section = FALSE;
421   filename_and_size.filename = file;
422   filename_and_size.filesize = 0;
423   bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
424 
425   if (!bfd_close (abfd))
426     {
427       bfd_nonfatal (file);
428       return FALSE;
429     }
430 
431   return got_a_section;
432 }
433 
434 /* Print the strings in FILE.  Return TRUE if ok, FALSE if an error occurs.  */
435 
436 static bfd_boolean
437 strings_file (char *file)
438 {
439   struct stat st;
440 
441   /* get_file_size does not support non-S_ISREG files.  */
442 
443   if (stat (file, &st) < 0)
444     {
445       if (errno == ENOENT)
446 	non_fatal (_("'%s': No such file"), file);
447       else
448 	non_fatal (_("Warning: could not locate '%s'.  reason: %s"),
449 		   file, strerror (errno));
450       return FALSE;
451     }
452 
453   /* If we weren't told to scan the whole file,
454      try to open it as an object file and only look at
455      initialized data sections.  If that fails, fall back to the
456      whole file.  */
457   if (!datasection_only || !strings_object_file (file))
458     {
459       FILE *stream;
460 
461       stream = fopen (file, FOPEN_RB);
462       if (stream == NULL)
463 	{
464 	  fprintf (stderr, "%s: ", program_name);
465 	  perror (file);
466 	  return FALSE;
467 	}
468 
469       print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
470 
471       if (fclose (stream) == EOF)
472 	{
473 	  fprintf (stderr, "%s: ", program_name);
474 	  perror (file);
475 	  return FALSE;
476 	}
477     }
478 
479   return TRUE;
480 }
481 
482 /* Read the next character, return EOF if none available.
483    Assume that STREAM is positioned so that the next byte read
484    is at address ADDRESS in the file.
485 
486    If STREAM is NULL, do not read from it.
487    The caller can supply a buffer of characters
488    to be processed before the data in STREAM.
489    MAGIC is the address of the buffer and
490    MAGICCOUNT is how many characters are in it.  */
491 
492 static long
493 get_char (FILE *stream, file_ptr *address, int *magiccount, char **magic)
494 {
495   int c, i;
496   long r = 0;
497 
498   for (i = 0; i < encoding_bytes; i++)
499     {
500       if (*magiccount)
501 	{
502 	  (*magiccount)--;
503 	  c = *(*magic)++;
504 	}
505       else
506 	{
507 	  if (stream == NULL)
508 	    return EOF;
509 
510 	  /* Only use getc_unlocked if we found a declaration for it.
511 	     Otherwise, libc is not thread safe by default, and we
512 	     should not use it.  */
513 
514 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
515 	  c = getc_unlocked (stream);
516 #else
517 	  c = getc (stream);
518 #endif
519 	  if (c == EOF)
520 	    return EOF;
521 	}
522 
523       (*address)++;
524       r = (r << 8) | (c & 0xff);
525     }
526 
527   switch (encoding)
528     {
529     default:
530       break;
531     case 'l':
532       r = ((r & 0xff) << 8) | ((r & 0xff00) >> 8);
533       break;
534     case 'L':
535       r = (((r & 0xff) << 24) | ((r & 0xff00) << 8)
536 	   | ((r & 0xff0000) >> 8) | ((r & 0xff000000) >> 24));
537       break;
538     }
539 
540   return r;
541 }
542 
543 /* Find the strings in file FILENAME, read from STREAM.
544    Assume that STREAM is positioned so that the next byte read
545    is at address ADDRESS in the file.
546    Stop reading at address STOP_POINT in the file, if nonzero.
547 
548    If STREAM is NULL, do not read from it.
549    The caller can supply a buffer of characters
550    to be processed before the data in STREAM.
551    MAGIC is the address of the buffer and
552    MAGICCOUNT is how many characters are in it.
553    Those characters come at address ADDRESS and the data in STREAM follow.  */
554 
555 static void
556 print_strings (const char *filename, FILE *stream, file_ptr address,
557 	       int stop_point, int magiccount, char *magic)
558 {
559   char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
560 
561   while (1)
562     {
563       file_ptr start;
564       int i;
565       long c;
566 
567       /* See if the next `string_min' chars are all graphic chars.  */
568     tryline:
569       if (stop_point && address >= stop_point)
570 	break;
571       start = address;
572       for (i = 0; i < string_min; i++)
573 	{
574 	  c = get_char (stream, &address, &magiccount, &magic);
575 	  if (c == EOF)
576 	    {
577 	      free (buf);
578 	      return;
579 	    }
580 	  if (! STRING_ISGRAPHIC (c))
581 	    /* Found a non-graphic.  Try again starting with next char.  */
582 	    goto tryline;
583 	  buf[i] = c;
584 	}
585 
586       /* We found a run of `string_min' graphic characters.  Print up
587 	 to the next non-graphic character.  */
588 
589       if (print_filenames)
590 	printf ("%s: ", filename);
591       if (print_addresses)
592 	switch (address_radix)
593 	  {
594 	  case 8:
595 #ifdef HAVE_LONG_LONG
596 	    if (sizeof (start) > sizeof (long))
597 	      {
598 # ifndef __MSVCRT__
599 	        printf ("%7llo ", (unsigned long long) start);
600 # else
601 	        printf ("%7I64o ", (unsigned long long) start);
602 # endif
603 	      }
604 	    else
605 #elif !BFD_HOST_64BIT_LONG
606 	    if (start != (unsigned long) start)
607 	      printf ("++%7lo ", (unsigned long) start);
608 	    else
609 #endif
610 	      printf ("%7lo ", (unsigned long) start);
611 	    break;
612 
613 	  case 10:
614 #ifdef HAVE_LONG_LONG
615 	    if (sizeof (start) > sizeof (long))
616 	      {
617 # ifndef __MSVCRT__
618 	        printf ("%7lld ", (unsigned long long) start);
619 # else
620 	        printf ("%7I64d ", (unsigned long long) start);
621 # endif
622 	      }
623 	    else
624 #elif !BFD_HOST_64BIT_LONG
625 	    if (start != (unsigned long) start)
626 	      printf ("++%7ld ", (unsigned long) start);
627 	    else
628 #endif
629 	      printf ("%7ld ", (long) start);
630 	    break;
631 
632 	  case 16:
633 #ifdef HAVE_LONG_LONG
634 	    if (sizeof (start) > sizeof (long))
635 	      {
636 # ifndef __MSVCRT__
637 	        printf ("%7llx ", (unsigned long long) start);
638 # else
639 	        printf ("%7I64x ", (unsigned long long) start);
640 # endif
641 	      }
642 	    else
643 #elif !BFD_HOST_64BIT_LONG
644 	    if (start != (unsigned long) start)
645 	      printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
646 		      (unsigned long) (start & 0xffffffff));
647 	    else
648 #endif
649 	      printf ("%7lx ", (unsigned long) start);
650 	    break;
651 	  }
652 
653       buf[i] = '\0';
654       fputs (buf, stdout);
655 
656       while (1)
657 	{
658 	  c = get_char (stream, &address, &magiccount, &magic);
659 	  if (c == EOF)
660 	    break;
661 	  if (! STRING_ISGRAPHIC (c))
662 	    break;
663 	  putchar (c);
664 	}
665 
666       if (output_separator)
667         fputs (output_separator, stdout);
668       else
669         putchar ('\n');
670     }
671   free (buf);
672 }
673 
674 static void
675 usage (FILE *stream, int status)
676 {
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"));
680 
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"));
685   else
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"));
689 
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);
707   exit (status);
708 }
709