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