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