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