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