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