Merge branch 'vendor/DIFFUTILS'
[dragonfly.git] / contrib / binutils-2.20 / 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, 2005, 2006, 2007, 2008, 2009
4    Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19    02110-1301, USA.  */
20 \f
21 /* Usage: strings [options] file...
22
23    Options:
24    --all
25    -a
26    -            Do not scan only the initialized data section of object files.
27
28    --print-file-name
29    -f           Print the name of the file before each string.
30
31    --bytes=min-len
32    -n min-len
33    -min-len     Print graphic char sequences, MIN-LEN or more bytes long,
34                 that are followed by a NUL or a newline.  Default is 4.
35
36    --radix={o,x,d}
37    -t {o,x,d}   Print the offset within the file before each string,
38                 in octal/hex/decimal.
39
40    -o           Like -to.  (Some other implementations have -o like -to,
41                 others like -td.  We chose one arbitrarily.)
42
43    --encoding={s,S,b,l,B,L}
44    -e {s,S,b,l,B,L}
45                 Select character encoding: 7-bit-character, 8-bit-character,
46                 bigendian 16-bit, littleendian 16-bit, bigendian 32-bit,
47                 littleendian 32-bit.
48
49    --target=BFDNAME
50    -T {bfdname}
51                 Specify a non-default object file format.
52
53    --help
54    -h           Print the usage message on the standard output.
55
56    --version
57    -V
58    -v           Print the program version number.
59
60    Written by Richard Stallman <rms@gnu.ai.mit.edu>
61    and David MacKenzie <djm@gnu.ai.mit.edu>.  */
62
63 #include "sysdep.h"
64 #include "bfd.h"
65 #include "getopt.h"
66 #include "libiberty.h"
67 #include "safe-ctype.h"
68 #include <sys/stat.h>
69 #include "bucomm.h"
70
71 #define STRING_ISGRAPHIC(c) \
72       (   (c) >= 0 \
73        && (c) <= 255 \
74        && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
75
76 #ifndef errno
77 extern int errno;
78 #endif
79
80 /* The BFD section flags that identify an initialized data section.  */
81 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
82
83 #ifdef HAVE_FOPEN64
84 typedef off64_t file_off;
85 #define file_open(s,m) fopen64(s, m)
86 #else
87 typedef off_t file_off;
88 #define file_open(s,m) fopen(s, m)
89 #endif
90 #ifdef HAVE_STAT64
91 typedef struct stat64 statbuf;
92 #define file_stat(f,s) stat64(f, s)
93 #else
94 typedef struct stat statbuf;
95 #define file_stat(f,s) stat(f, s)
96 #endif
97
98 /* Radix for printing addresses (must be 8, 10 or 16).  */
99 static int address_radix;
100
101 /* Minimum length of sequence of graphic chars to trigger output.  */
102 static int string_min;
103
104 /* TRUE means print address within file for each string.  */
105 static bfd_boolean print_addresses;
106
107 /* TRUE means print filename for each string.  */
108 static bfd_boolean print_filenames;
109
110 /* TRUE means for object files scan only the data section.  */
111 static bfd_boolean datasection_only;
112
113 /* TRUE if we found an initialized data section in the current file.  */
114 static bfd_boolean got_a_section;
115
116 /* The BFD object file format.  */
117 static char *target;
118
119 /* The character encoding format.  */
120 static char encoding;
121 static int encoding_bytes;
122
123 static struct option long_options[] =
124 {
125   {"all", no_argument, NULL, 'a'},
126   {"print-file-name", no_argument, NULL, 'f'},
127   {"bytes", required_argument, NULL, 'n'},
128   {"radix", required_argument, NULL, 't'},
129   {"encoding", required_argument, NULL, 'e'},
130   {"target", required_argument, NULL, 'T'},
131   {"help", no_argument, NULL, 'h'},
132   {"version", no_argument, NULL, 'v'},
133   {NULL, 0, NULL, 0}
134 };
135
136 /* Records the size of a named file so that we
137    do not repeatedly run bfd_stat() on it.  */
138
139 typedef struct
140 {
141   const char *  filename;
142   bfd_size_type filesize;
143 } filename_and_size_t;
144
145 static void strings_a_section (bfd *, asection *, void *);
146 static bfd_boolean strings_object_file (const char *);
147 static bfd_boolean strings_file (char *file);
148 static void print_strings (const char *, FILE *, file_off, int, int, char *);
149 static void usage (FILE *, int);
150 static long get_char (FILE *, file_off *, int *, char **);
151 \f
152 int main (int, char **);
153
154 int
155 main (int argc, char **argv)
156 {
157   int optc;
158   int exit_status = 0;
159   bfd_boolean files_given = FALSE;
160   char *s;
161   int numeric_opt = 0;
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
172   expandargv (&argc, &argv);
173
174   string_min = 4;
175   print_addresses = FALSE;
176   print_filenames = FALSE;
177   datasection_only = TRUE;
178   target = NULL;
179   encoding = 's';
180
181   while ((optc = getopt_long (argc, argv, "afhHn:ot:e:T:Vv0123456789",
182                               long_options, (int *) 0)) != EOF)
183     {
184       switch (optc)
185         {
186         case 'a':
187           datasection_only = FALSE;
188           break;
189
190         case 'f':
191           print_filenames = TRUE;
192           break;
193
194         case 'H':
195         case 'h':
196           usage (stdout, 0);
197
198         case 'n':
199           string_min = (int) strtoul (optarg, &s, 0);
200           if (s != NULL && *s != 0)
201             fatal (_("invalid integer argument %s"), optarg);
202           break;
203
204         case 'o':
205           print_addresses = TRUE;
206           address_radix = 8;
207           break;
208
209         case 't':
210           print_addresses = TRUE;
211           if (optarg[1] != '\0')
212             usage (stderr, 1);
213           switch (optarg[0])
214             {
215             case 'o':
216               address_radix = 8;
217               break;
218
219             case 'd':
220               address_radix = 10;
221               break;
222
223             case 'x':
224               address_radix = 16;
225               break;
226
227             default:
228               usage (stderr, 1);
229             }
230           break;
231
232         case 'T':
233           target = optarg;
234           break;
235
236         case 'e':
237           if (optarg[1] != '\0')
238             usage (stderr, 1);
239           encoding = optarg[0];
240           break;
241
242         case 'V':
243         case 'v':
244           print_version ("strings");
245           break;
246
247         case '?':
248           usage (stderr, 1);
249
250         default:
251           numeric_opt = optind;
252           break;
253         }
254     }
255
256   if (numeric_opt != 0)
257     {
258       string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0);
259       if (s != NULL && *s != 0)
260         fatal (_("invalid integer argument %s"), argv[numeric_opt - 1] + 1);
261     }
262   if (string_min < 1)
263     fatal (_("invalid minimum string length %d"), string_min);
264
265   switch (encoding)
266     {
267     case 'S':
268     case 's':
269       encoding_bytes = 1;
270       break;
271     case 'b':
272     case 'l':
273       encoding_bytes = 2;
274       break;
275     case 'B':
276     case 'L':
277       encoding_bytes = 4;
278       break;
279     default:
280       usage (stderr, 1);
281     }
282
283   bfd_init ();
284   set_default_bfd_target ();
285
286   if (optind >= argc)
287     {
288       datasection_only = FALSE;
289       SET_BINARY (fileno (stdin));
290       print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
291       files_given = TRUE;
292     }
293   else
294     {
295       for (; optind < argc; ++optind)
296         {
297           if (strcmp (argv[optind], "-") == 0)
298             datasection_only = FALSE;
299           else
300             {
301               files_given = TRUE;
302               exit_status |= strings_file (argv[optind]) == FALSE;
303             }
304         }
305     }
306
307   if (!files_given)
308     usage (stderr, 1);
309
310   return (exit_status);
311 }
312 \f
313 /* Scan section SECT of the file ABFD, whose printable name is in
314    ARG->filename and whose size might be in ARG->filesize.  If it
315    contains initialized data set `got_a_section' and print the
316    strings in it.
317
318    FIXME: We ought to be able to return error codes/messages for
319    certain conditions.  */
320
321 static void
322 strings_a_section (bfd *abfd, asection *sect, void *arg)
323 {
324   filename_and_size_t * filename_and_sizep;
325   bfd_size_type *filesizep;
326   bfd_size_type sectsize;
327   void *mem;
328      
329   if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
330     return;
331
332   sectsize = bfd_get_section_size (sect);
333      
334   if (sectsize <= 0)
335     return;
336
337   /* Get the size of the file.  This might have been cached for us.  */
338   filename_and_sizep = (filename_and_size_t *) arg;
339   filesizep = & filename_and_sizep->filesize;
340
341   if (*filesizep == 0)
342     {
343       struct stat st;
344       
345       if (bfd_stat (abfd, &st))
346         return;
347
348       /* Cache the result so that we do not repeatedly stat this file.  */
349       *filesizep = st.st_size;
350     }
351
352   /* Compare the size of the section against the size of the file.
353      If the section is bigger then the file must be corrupt and
354      we should not try dumping it.  */
355   if (sectsize >= *filesizep)
356     return;
357
358   mem = xmalloc (sectsize);
359
360   if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
361     {
362       got_a_section = TRUE;
363
364       print_strings (filename_and_sizep->filename, NULL, sect->filepos,
365                      0, sectsize, (char *) mem);
366     }
367
368   free (mem);
369 }
370
371 /* Scan all of the sections in FILE, and print the strings
372    in the initialized data section(s).
373
374    Return TRUE if successful,
375    FALSE if not (such as if FILE is not an object file).  */
376
377 static bfd_boolean
378 strings_object_file (const char *file)
379 {
380   filename_and_size_t filename_and_size;
381   bfd *abfd;
382
383   abfd = bfd_openr (file, target);
384
385   if (abfd == NULL)
386     /* Treat the file as a non-object file.  */
387     return FALSE;
388
389   /* This call is mainly for its side effect of reading in the sections.
390      We follow the traditional behavior of `strings' in that we don't
391      complain if we don't recognize a file to be an object file.  */
392   if (!bfd_check_format (abfd, bfd_object))
393     {
394       bfd_close (abfd);
395       return FALSE;
396     }
397
398   got_a_section = FALSE;
399   filename_and_size.filename = file;
400   filename_and_size.filesize = 0;
401   bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
402
403   if (!bfd_close (abfd))
404     {
405       bfd_nonfatal (file);
406       return FALSE;
407     }
408
409   return got_a_section;
410 }
411
412 /* Print the strings in FILE.  Return TRUE if ok, FALSE if an error occurs.  */
413
414 static bfd_boolean
415 strings_file (char *file)
416 {
417   statbuf st;
418
419   if (file_stat (file, &st) < 0)
420     {
421       if (errno == ENOENT)
422         non_fatal (_("'%s': No such file"), file);
423       else
424         non_fatal (_("Warning: could not locate '%s'.  reason: %s"),
425                    file, strerror (errno));
426       return FALSE;
427     }
428
429   /* If we weren't told to scan the whole file,
430      try to open it as an object file and only look at
431      initialized data sections.  If that fails, fall back to the
432      whole file.  */
433   if (!datasection_only || !strings_object_file (file))
434     {
435       FILE *stream;
436
437       stream = file_open (file, FOPEN_RB);
438       if (stream == NULL)
439         {
440           fprintf (stderr, "%s: ", program_name);
441           perror (file);
442           return FALSE;
443         }
444
445       print_strings (file, stream, (file_off) 0, 0, 0, (char *) 0);
446
447       if (fclose (stream) == EOF)
448         {
449           fprintf (stderr, "%s: ", program_name);
450           perror (file);
451           return FALSE;
452         }
453     }
454
455   return TRUE;
456 }
457 \f
458 /* Read the next character, return EOF if none available.
459    Assume that STREAM is positioned so that the next byte read
460    is at address ADDRESS in the file.
461
462    If STREAM is NULL, do not read from it.
463    The caller can supply a buffer of characters
464    to be processed before the data in STREAM.
465    MAGIC is the address of the buffer and
466    MAGICCOUNT is how many characters are in it.  */
467
468 static long
469 get_char (FILE *stream, file_off *address, int *magiccount, char **magic)
470 {
471   int c, i;
472   long r = EOF;
473   unsigned char buf[4];
474
475   for (i = 0; i < encoding_bytes; i++)
476     {
477       if (*magiccount)
478         {
479           (*magiccount)--;
480           c = *(*magic)++;
481         }
482       else
483         {
484           if (stream == NULL)
485             return EOF;
486
487           /* Only use getc_unlocked if we found a declaration for it.
488              Otherwise, libc is not thread safe by default, and we
489              should not use it.  */
490
491 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
492           c = getc_unlocked (stream);
493 #else
494           c = getc (stream);
495 #endif
496           if (c == EOF)
497             return EOF;
498         }
499
500       (*address)++;
501       buf[i] = c;
502     }
503
504   switch (encoding)
505     {
506     case 'S':
507     case 's':
508       r = buf[0];
509       break;
510     case 'b':
511       r = (buf[0] << 8) | buf[1];
512       break;
513     case 'l':
514       r = buf[0] | (buf[1] << 8);
515       break;
516     case 'B':
517       r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
518         ((long) buf[2] << 8) | buf[3];
519       break;
520     case 'L':
521       r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
522         ((long) buf[3] << 24);
523       break;
524     }
525
526   if (r == EOF)
527     return 0;
528
529   return r;
530 }
531 \f
532 /* Find the strings in file FILENAME, read from STREAM.
533    Assume that STREAM is positioned so that the next byte read
534    is at address ADDRESS in the file.
535    Stop reading at address STOP_POINT in the file, if nonzero.
536
537    If STREAM is NULL, do not read from it.
538    The caller can supply a buffer of characters
539    to be processed before the data in STREAM.
540    MAGIC is the address of the buffer and
541    MAGICCOUNT is how many characters are in it.
542    Those characters come at address ADDRESS and the data in STREAM follow.  */
543
544 static void
545 print_strings (const char *filename, FILE *stream, file_off address,
546                int stop_point, int magiccount, char *magic)
547 {
548   char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
549
550   while (1)
551     {
552       file_off start;
553       int i;
554       long c;
555
556       /* See if the next `string_min' chars are all graphic chars.  */
557     tryline:
558       if (stop_point && address >= stop_point)
559         break;
560       start = address;
561       for (i = 0; i < string_min; i++)
562         {
563           c = get_char (stream, &address, &magiccount, &magic);
564           if (c == EOF)
565             return;
566           if (! STRING_ISGRAPHIC (c))
567             /* Found a non-graphic.  Try again starting with next char.  */
568             goto tryline;
569           buf[i] = c;
570         }
571
572       /* We found a run of `string_min' graphic characters.  Print up
573          to the next non-graphic character.  */
574
575       if (print_filenames)
576         printf ("%s: ", filename);
577       if (print_addresses)
578         switch (address_radix)
579           {
580           case 8:
581 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
582             if (sizeof (start) > sizeof (long))
583               {
584 #ifndef __MSVCRT__
585                 printf ("%7llo ", (unsigned long long) start);
586 #else
587                 printf ("%7I64o ", (unsigned long long) start);
588 #endif
589               }
590             else
591 #elif !BFD_HOST_64BIT_LONG
592             if (start != (unsigned long) start)
593               printf ("++%7lo ", (unsigned long) start);
594             else
595 #endif
596               printf ("%7lo ", (unsigned long) start);
597             break;
598
599           case 10:
600 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
601             if (sizeof (start) > sizeof (long))
602               {
603 #ifndef __MSVCRT__
604                 printf ("%7lld ", (unsigned long long) start);
605 #else
606                 printf ("%7I64d ", (unsigned long long) start);
607 #endif
608               }
609             else
610 #elif !BFD_HOST_64BIT_LONG
611             if (start != (unsigned long) start)
612               printf ("++%7ld ", (unsigned long) start);
613             else
614 #endif
615               printf ("%7ld ", (long) start);
616             break;
617
618           case 16:
619 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
620             if (sizeof (start) > sizeof (long))
621               {
622 #ifndef __MSVCRT__
623                 printf ("%7llx ", (unsigned long long) start);
624 #else
625                 printf ("%7I64x ", (unsigned long long) start);
626 #endif
627               }
628             else
629 #elif !BFD_HOST_64BIT_LONG
630             if (start != (unsigned long) start)
631               printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
632                       (unsigned long) (start & 0xffffffff));
633             else
634 #endif
635               printf ("%7lx ", (unsigned long) start);
636             break;
637           }
638
639       buf[i] = '\0';
640       fputs (buf, stdout);
641
642       while (1)
643         {
644           c = get_char (stream, &address, &magiccount, &magic);
645           if (c == EOF)
646             break;
647           if (! STRING_ISGRAPHIC (c))
648             break;
649           putchar (c);
650         }
651
652       putchar ('\n');
653     }
654 }
655 \f
656 static void
657 usage (FILE *stream, int status)
658 {
659   fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
660   fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
661   fprintf (stream, _(" The options are:\n\
662   -a - --all                Scan the entire file, not just the data section\n\
663   -f --print-file-name      Print the name of the file before each string\n\
664   -n --bytes=[number]       Locate & print any NUL-terminated sequence of at\n\
665   -<number>                   least [number] characters (default 4).\n\
666   -t --radix={o,d,x}        Print the location of the string in base 8, 10 or 16\n\
667   -o                        An alias for --radix=o\n\
668   -T --target=<BFDNAME>     Specify the binary file format\n\
669   -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
670                             s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
671   @<file>                   Read options from <file>\n\
672   -h --help                 Display this information\n\
673   -v -V --version           Print the program's version number\n"));
674   list_supported_targets (program_name, stream);
675   if (REPORT_BUGS_TO[0] && status == 0)
676     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
677   exit (status);
678 }