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