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