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