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