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