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