* strings.c (statbuf): New typedef.
[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, 2003, 2004 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 #ifdef HAVE_STAT64
108 typedef struct stat64 statbuf;
109 #define file_stat(f,s) stat64(f, s)
110 #else
111 typedef struct stat statbuf;
112 #define file_stat(f,s) stat(f, s)
113 #endif
114
115 /* Radix for printing addresses (must be 8, 10 or 16).  */
116 static int address_radix;
117
118 /* Minimum length of sequence of graphic chars to trigger output.  */
119 static int string_min;
120
121 /* TRUE means print address within file for each string.  */
122 static bfd_boolean print_addresses;
123
124 /* TRUE means print filename for each string.  */
125 static bfd_boolean print_filenames;
126
127 /* TRUE means for object files scan only the data section.  */
128 static bfd_boolean datasection_only;
129
130 /* TRUE if we found an initialized data section in the current file.  */
131 static bfd_boolean got_a_section;
132
133 /* The BFD object file format.  */
134 static char *target;
135
136 /* The character encoding format.  */
137 static char encoding;
138 static int encoding_bytes;
139
140 static struct option long_options[] =
141 {
142   {"all", no_argument, NULL, 'a'},
143   {"print-file-name", no_argument, NULL, 'f'},
144   {"bytes", required_argument, NULL, 'n'},
145   {"radix", required_argument, NULL, 't'},
146   {"encoding", required_argument, NULL, 'e'},
147   {"target", required_argument, NULL, 'T'},
148   {"help", no_argument, NULL, 'h'},
149   {"version", no_argument, NULL, 'v'},
150   {NULL, 0, NULL, 0}
151 };
152
153 static void strings_a_section (bfd *, asection *, void *);
154 static bfd_boolean strings_object_file (const char *);
155 static bfd_boolean strings_file (char *file);
156 static int integer_arg (char *s);
157 static void print_strings (const char *, FILE *, file_off, int, int, char *);
158 static void usage (FILE *, int);
159 static long get_char (FILE *, file_off *, int *, char **);
160 \f
161 int main (int, char **);
162
163 int
164 main (int argc, 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             fatal (_("invalid number %s"), optarg);
206           break;
207
208         case 'o':
209           print_addresses = TRUE;
210           address_radix = 8;
211           break;
212
213         case 't':
214           print_addresses = TRUE;
215           if (optarg[1] != '\0')
216             usage (stderr, 1);
217           switch (optarg[0])
218             {
219             case 'o':
220               address_radix = 8;
221               break;
222
223             case 'd':
224               address_radix = 10;
225               break;
226
227             case 'x':
228               address_radix = 16;
229               break;
230
231             default:
232               usage (stderr, 1);
233             }
234           break;
235
236         case 'T':
237           target = optarg;
238           break;
239
240         case 'e':
241           if (optarg[1] != '\0')
242             usage (stderr, 1);
243           encoding = optarg[0];
244           break;
245
246         case 'V':
247         case 'v':
248           print_version ("strings");
249           break;
250
251         case '?':
252           usage (stderr, 1);
253
254         default:
255           if (string_min < 0)
256             string_min = optc - '0';
257           else
258             string_min = string_min * 10 + optc - '0';
259           break;
260         }
261     }
262
263   if (string_min < 0)
264     string_min = 4;
265
266   switch (encoding)
267     {
268     case 'S':
269     case 's':
270       encoding_bytes = 1;
271       break;
272     case 'b':
273     case 'l':
274       encoding_bytes = 2;
275       break;
276     case 'B':
277     case 'L':
278       encoding_bytes = 4;
279       break;
280     default:
281       usage (stderr, 1);
282     }
283
284   bfd_init ();
285   set_default_bfd_target ();
286
287   if (optind >= argc)
288     {
289       datasection_only = FALSE;
290 #ifdef SET_BINARY
291       SET_BINARY (fileno (stdin));
292 #endif
293       print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
294       files_given = TRUE;
295     }
296   else
297     {
298       for (; optind < argc; ++optind)
299         {
300           if (strcmp (argv[optind], "-") == 0)
301             datasection_only = FALSE;
302           else
303             {
304               files_given = TRUE;
305               exit_status |= strings_file (argv[optind]) == FALSE;
306             }
307         }
308     }
309
310   if (!files_given)
311     usage (stderr, 1);
312
313   return (exit_status);
314 }
315 \f
316 /* Scan section SECT of the file ABFD, whose printable name is FILE.
317    If it contains initialized data,
318    set `got_a_section' and print the strings in it.  */
319
320 static void
321 strings_a_section (bfd *abfd, asection *sect, void *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 (sect);
328       void *mem = xmalloc (sz);
329
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 bfd_boolean
346 strings_object_file (const char *file)
347 {
348   bfd *abfd = bfd_openr (file, target);
349
350   if (abfd == NULL)
351     /* Treat the file as a non-object file.  */
352     return FALSE;
353
354   /* This call is mainly for its side effect of reading in the sections.
355      We follow the traditional behavior of `strings' in that we don't
356      complain if we don't recognize a file to be an object file.  */
357   if (!bfd_check_format (abfd, bfd_object))
358     {
359       bfd_close (abfd);
360       return FALSE;
361     }
362
363   got_a_section = FALSE;
364   bfd_map_over_sections (abfd, strings_a_section, (void *) file);
365
366   if (!bfd_close (abfd))
367     {
368       bfd_nonfatal (file);
369       return FALSE;
370     }
371
372   return got_a_section;
373 }
374
375 /* Print the strings in FILE.  Return TRUE if ok, FALSE if an error occurs.  */
376
377 static bfd_boolean
378 strings_file (char *file)
379 {
380   statbuf st;
381
382   if (file_stat (file, &st) < 0)
383     {
384       if (errno == ENOENT)
385         non_fatal (_("'%s': No such file"), file);
386       else
387         non_fatal (_("Warning: could not locate '%s'.  reason: %s"),
388                    file, strerror (errno));
389       return FALSE;
390     }
391
392   /* If we weren't told to scan the whole file,
393      try to open it as an object file and only look at
394      initialized data sections.  If that fails, fall back to the
395      whole file.  */
396   if (!datasection_only || !strings_object_file (file))
397     {
398       FILE *stream;
399
400       stream = file_open (file, FOPEN_RB);
401       if (stream == NULL)
402         {
403           fprintf (stderr, "%s: ", program_name);
404           perror (file);
405           return FALSE;
406         }
407
408       print_strings (file, stream, (file_off) 0, 0, 0, (char *) 0);
409
410       if (fclose (stream) == EOF)
411         {
412           fprintf (stderr, "%s: ", program_name);
413           perror (file);
414           return FALSE;
415         }
416     }
417
418   return TRUE;
419 }
420 \f
421 /* Read the next character, return EOF if none available.
422    Assume that STREAM is positioned so that the next byte read
423    is at address ADDRESS in the file.
424
425    If STREAM is NULL, do not read from it.
426    The caller can supply a buffer of characters
427    to be processed before the data in STREAM.
428    MAGIC is the address of the buffer and
429    MAGICCOUNT is how many characters are in it.  */
430
431 static long
432 get_char (FILE *stream, file_off *address, int *magiccount, 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 (const char *filename, FILE *stream, file_off address,
504                int stop_point, int magiccount, 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 (! STRING_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 ", (unsigned long) (start >> 32),
577                       (unsigned long) (start & 0xffffffff));
578             else
579 # endif
580 #endif
581               printf ("%7lx ", (unsigned long) start);
582             break;
583           }
584
585       buf[i] = '\0';
586       fputs (buf, stdout);
587
588       while (1)
589         {
590           c = get_char (stream, &address, &magiccount, &magic);
591           if (c == EOF)
592             break;
593           if (! STRING_ISGRAPHIC (c))
594             break;
595           putchar (c);
596         }
597
598       putchar ('\n');
599     }
600 }
601 \f
602 /* Parse string S as an integer, using decimal radix by default,
603    but allowing octal and hex numbers as in C.  */
604
605 static int
606 integer_arg (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     fatal (_("invalid integer argument %s"), s);
643
644   return value;
645 }
646
647 static void
648 usage (FILE *stream, int status)
649 {
650   fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
651   fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
652   fprintf (stream, _(" The options are:\n\
653   -a - --all                Scan the entire file, not just the data section\n\
654   -f --print-file-name      Print the name of the file before each string\n\
655   -n --bytes=[number]       Locate & print any NUL-terminated sequence of at\n\
656   -<number>                 least [number] characters (default 4).\n\
657   -t --radix={o,x,d}        Print the location of the string in base 8, 10 or 16\n\
658   -o                        An alias for --radix=o\n\
659   -T --target=<BFDNAME>     Specify the binary file format\n\
660   -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
661                             s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
662   -h --help                 Display this information\n\
663   -v --version              Print the program's version number\n"));
664   list_supported_targets (program_name, stream);
665   if (status == 0)
666     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
667   exit (status);
668 }