Add new command line option '--encoding' to strings
[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 #include "bfd.h"
60 #include <stdio.h>
61 #include <getopt.h>
62 #include <ctype.h>
63 #include <errno.h>
64 #include "bucomm.h"
65 #include "libiberty.h"
66
67 /* Some platforms need to put stdin into binary mode, to read
68     binary files.  */
69 #ifdef HAVE_SETMODE
70 #ifndef O_BINARY
71 #ifdef _O_BINARY
72 #define O_BINARY _O_BINARY
73 #define setmode _setmode
74 #else
75 #define O_BINARY 0
76 #endif
77 #endif
78 #if O_BINARY
79 #include <io.h>
80 #define SET_BINARY(f) do { if (!isatty(f)) setmode(f,O_BINARY); } while (0)
81 #endif
82 #endif
83
84 /* Not all printable characters have ASCII codes (depending upon the
85    LOCALE set) but on some older systems it is not safe to test isprint
86    without first testing isascii...  */
87 #if defined isascii && !defined HAVE_LOCALE_H
88 #define isgraphic(c) (isascii (c) && (isprint (c) || (c) == '\t'))
89 #else
90 #define isgraphic(c) (isprint (c) || (c) == '\t')
91 #endif
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 /* Radix for printing addresses (must be 8, 10 or 16).  */
101 static int address_radix;
102
103 /* Minimum length of sequence of graphic chars to trigger output.  */
104 static int string_min;
105
106 /* true means print address within file for each string.  */
107 static boolean print_addresses;
108
109 /* true means print filename for each string.  */
110 static boolean print_filenames;
111
112 /* true means for object files scan only the data section.  */
113 static boolean datasection_only;
114
115 /* true if we found an initialized data section in the current file.  */
116 static boolean got_a_section;
117
118 /* The BFD object file format.  */
119 static char *target;
120
121 /* The character encoding format.  */
122 static char encoding;
123 static int encoding_bytes;
124
125 static struct option long_options[] =
126 {
127   {"all", no_argument, NULL, 'a'},
128   {"print-file-name", no_argument, NULL, 'f'},
129   {"bytes", required_argument, NULL, 'n'},
130   {"radix", required_argument, NULL, 't'},
131   {"encoding", required_argument, NULL, 'e'},
132   {"target", required_argument, NULL, 'T'},
133   {"help", no_argument, NULL, 'h'},
134   {"version", no_argument, NULL, 'v'},
135   {NULL, 0, NULL, 0}
136 };
137
138 static void strings_a_section PARAMS ((bfd *, asection *, PTR));
139 static boolean strings_object_file PARAMS ((const char *));
140 static boolean strings_file PARAMS ((char *file));
141 static int integer_arg PARAMS ((char *s));
142 static void print_strings PARAMS ((const char *filename, FILE *stream,
143                                   file_ptr address, int stop_point,
144                                   int magiccount, char *magic));
145 static void usage PARAMS ((FILE *stream, int status));
146 \f
147 int
148 main (argc, argv)
149      int argc;
150      char **argv;
151 {
152   int optc;
153   int exit_status = 0;
154   boolean files_given = false;
155
156 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
157   setlocale (LC_ALL, "");
158 #endif
159   bindtextdomain (PACKAGE, LOCALEDIR);
160   textdomain (PACKAGE);
161
162   program_name = argv[0];
163   xmalloc_set_program_name (program_name);
164   string_min = -1;
165   print_addresses = false;
166   print_filenames = false;
167   datasection_only = true;
168   target = NULL;
169   encoding = 's';
170
171   while ((optc = getopt_long (argc, argv, "afn:ot:e:v0123456789",
172                               long_options, (int *) 0)) != EOF)
173     {
174       switch (optc)
175         {
176         case 'a':
177           datasection_only = false;
178           break;
179
180         case 'f':
181           print_filenames = true;
182           break;
183
184         case 'h':
185           usage (stdout, 0);
186
187         case 'n':
188           string_min = integer_arg (optarg);
189           if (string_min < 1)
190             {
191               fatal (_("invalid number %s"), optarg);
192             }
193           break;
194
195         case 'o':
196           print_addresses = true;
197           address_radix = 8;
198           break;
199
200         case 't':
201           print_addresses = true;
202           if (optarg[1] != '\0')
203             usage (stderr, 1);
204           switch (optarg[0])
205             {
206             case 'o':
207               address_radix = 8;
208               break;
209
210             case 'd':
211               address_radix = 10;
212               break;
213
214             case 'x':
215               address_radix = 16;
216               break;
217
218             default:
219               usage (stderr, 1);
220             }
221           break;
222
223         case 'T':
224           target = optarg;
225           break;
226
227         case 'e':
228           if (optarg[1] != '\0')
229             usage (stderr, 1);
230           encoding = optarg[0];
231           break;
232
233         case 'v':
234           print_version ("strings");
235           break;
236
237         case '?':
238           usage (stderr, 1);
239
240         default:
241           if (string_min < 0)
242             string_min = optc - '0';
243           else
244             string_min = string_min * 10 + optc - '0';
245           break;
246         }
247     }
248
249   if (string_min < 0)
250     string_min = 4;
251
252   switch (encoding)
253     {
254     case 's':
255       encoding_bytes = 1;
256       break;
257     case 'b':
258     case 'l':
259       encoding_bytes = 2;
260       break;
261     case 'B':
262     case 'L':
263       encoding_bytes = 4;
264       break;
265     default:
266       usage (stderr, 1);
267     }
268
269   bfd_init ();
270   set_default_bfd_target ();
271
272   if (optind >= argc)
273     {
274       datasection_only = false;
275 #ifdef SET_BINARY
276       SET_BINARY (fileno (stdin));
277 #endif
278       print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
279       files_given = true;
280     }
281   else
282     {
283       for (; optind < argc; ++optind)
284         {
285           if (strcmp (argv[optind], "-") == 0)
286             datasection_only = false;
287           else
288             {
289               files_given = true;
290               exit_status |= (strings_file (argv[optind]) == false);
291             }
292         }
293     }
294
295   if (files_given == false)
296     usage (stderr, 1);
297
298   return (exit_status);
299 }
300 \f
301 /* Scan section SECT of the file ABFD, whose printable name is FILE.
302    If it contains initialized data,
303    set `got_a_section' and print the strings in it.  */
304
305 static void
306 strings_a_section (abfd, sect, filearg)
307      bfd *abfd;
308      asection *sect;
309      PTR filearg;
310 {
311   const char *file = (const char *) filearg;
312
313   if ((sect->flags & DATA_FLAGS) == DATA_FLAGS)
314     {
315       bfd_size_type sz = bfd_get_section_size_before_reloc (sect);
316       PTR mem = xmalloc (sz);
317       if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz))
318         {
319           got_a_section = true;
320           print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
321         }
322       free (mem);
323     }
324 }
325
326 /* Scan all of the sections in FILE, and print the strings
327    in the initialized data section(s).
328
329    Return true if successful,
330    false if not (such as if FILE is not an object file).  */
331
332 static boolean
333 strings_object_file (file)
334      const char *file;
335 {
336   bfd *abfd = bfd_openr (file, target);
337
338   if (abfd == NULL)
339     {
340       /* Treat the file as a non-object file.  */
341       return false;
342     }
343
344   /* This call is mainly for its side effect of reading in the sections.
345      We follow the traditional behavior of `strings' in that we don't
346      complain if we don't recognize a file to be an object file.  */
347   if (bfd_check_format (abfd, bfd_object) == false)
348     {
349       bfd_close (abfd);
350       return false;
351     }
352
353   got_a_section = false;
354   bfd_map_over_sections (abfd, strings_a_section, (PTR) file);
355
356   if (!bfd_close (abfd))
357     {
358       bfd_nonfatal (file);
359       return false;
360     }
361
362   return got_a_section;
363 }
364
365 /* Print the strings in FILE.  Return true if ok, false if an error occurs.  */
366
367 static boolean
368 strings_file (file)
369      char *file;
370 {
371   /* If we weren't told to scan the whole file,
372      try to open it as an object file and only look at
373      initialized data sections.  If that fails, fall back to the
374      whole file.  */
375   if (!datasection_only || !strings_object_file (file))
376     {
377       FILE *stream;
378
379       stream = fopen (file, "rb");
380       /* Not all systems permit "rb", so try "r" if it failed.  */
381       if (stream == NULL)
382         stream = fopen (file, "r");
383       if (stream == NULL)
384         {
385           fprintf (stderr, "%s: ", program_name);
386           perror (file);
387           return false;
388         }
389
390       print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
391
392       if (fclose (stream) == EOF)
393         {
394           fprintf (stderr, "%s: ", program_name);
395           perror (file);
396           return false;
397         }
398     }
399
400   return true;
401 }
402 \f
403 /* Read the next character, return EOF if none available.
404    Assume that STREAM is positioned so that the next byte read
405    is at address ADDRESS in the file.
406
407    If STREAM is NULL, do not read from it.
408    The caller can supply a buffer of characters
409    to be processed before the data in STREAM.
410    MAGIC is the address of the buffer and
411    MAGICCOUNT is how many characters are in it.  */
412
413 static long
414 get_char (stream, address, magiccount, magic)
415      FILE *stream;
416      file_ptr *address;
417      int *magiccount;
418      char **magic;
419 {
420   int c, i;
421   long r;
422   unsigned char buf[4];
423
424   for (i = 0; i < encoding_bytes; i++)
425     {
426       if (*magiccount)
427         {
428           (*magiccount)--;
429           c = *(*magic)++;
430         }
431       else
432         {
433           if (stream == NULL)
434             return EOF;
435           c = getc (stream);
436           if (c == EOF)
437             return EOF;
438         }
439
440       (*address)++;
441       buf[i] = c;
442     }
443
444   switch (encoding)
445     {
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 (filename, stream, address, stop_point, magiccount, magic)
485      const char *filename;
486      FILE *stream;
487      file_ptr address;
488      int stop_point;
489      int magiccount;
490      char *magic;
491 {
492   char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
493
494   while (1)
495     {
496       file_ptr start;
497       int i;
498       long c;
499
500       /* See if the next `string_min' chars are all graphic chars.  */
501     tryline:
502       if (stop_point && address >= stop_point)
503         break;
504       start = address;
505       for (i = 0; i < string_min; i++)
506         {
507           c = get_char (stream, &address, &magiccount, &magic);
508           if (c == EOF)
509             return;
510           if (c > 255 || c < 0 || !isgraphic (c))
511             /* Found a non-graphic.  Try again starting with next char.  */
512             goto tryline;
513           buf[i] = c;
514         }
515
516       /* We found a run of `string_min' graphic characters.  Print up
517          to the next non-graphic character.  */
518
519       if (print_filenames)
520         printf ("%s: ", filename);
521       if (print_addresses)
522         switch (address_radix)
523           {
524           case 8:
525             printf ("%7lo ", (unsigned long) start);
526             break;
527
528           case 10:
529             printf ("%7ld ", (long) start);
530             break;
531
532           case 16:
533             printf ("%7lx ", (unsigned long) start);
534             break;
535           }
536
537       buf[i] = '\0';
538       fputs (buf, stdout);
539
540       while (1)
541         {
542           c = get_char (stream, &address, &magiccount, &magic);
543           if (c == EOF)
544             break;
545           if (c > 255 || c < 0 || !isgraphic (c))
546             break;
547           putchar (c);
548         }
549
550       putchar ('\n');
551     }
552 }
553 \f
554 /* Parse string S as an integer, using decimal radix by default,
555    but allowing octal and hex numbers as in C.  */
556
557 static int
558 integer_arg (s)
559      char *s;
560 {
561   int value;
562   int radix = 10;
563   char *p = s;
564   int c;
565
566   if (*p != '0')
567     radix = 10;
568   else if (*++p == 'x')
569     {
570       radix = 16;
571       p++;
572     }
573   else
574     radix = 8;
575
576   value = 0;
577   while (((c = *p++) >= '0' && c <= '9')
578          || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
579     {
580       value *= radix;
581       if (c >= '0' && c <= '9')
582         value += c - '0';
583       else
584         value += (c & ~40) - 'A';
585     }
586
587   if (c == 'b')
588     value *= 512;
589   else if (c == 'B')
590     value *= 1024;
591   else
592     p--;
593
594   if (*p)
595     {
596       fatal (_("invalid integer argument %s"), s);
597     }
598   return value;
599 }
600
601 static void
602 usage (stream, status)
603      FILE *stream;
604      int status;
605 {
606   fprintf (stream, _("\
607 Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-e {s,b,l,B,L}]\n\
608        [-] [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
609        [--target=bfdname] [--encoding {s,b,l,B,L}] [--help] [--version] file...\n"),
610            program_name);
611   list_supported_targets (program_name, stream);
612   if (status == 0)
613     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
614   exit (status);
615 }