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