2008-03-13 Paolo Bonzini <bonzini@gnu.org>
[binutils.git] / binutils / strings.c
blob40b53b8fed5cde5f6b1994cc19267a0140feef35
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 Free Software Foundation, Inc.
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 3, or (at your option)
8 any later version.
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.
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., 51 Franklin Street - Fifth Floor, Boston, MA
18 02110-1301, USA. */
20 /* Usage: strings [options] file...
22 Options:
23 --all
25 - Do not scan only the initialized data section of object files.
27 --print-file-name
28 -f Print the name of the file before each string.
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.
35 --radix={o,x,d}
36 -t {o,x,d} Print the offset within the file before each string,
37 in octal/hex/decimal.
39 -o Like -to. (Some other implementations have -o like -to,
40 others like -td. We chose one arbitrarily.)
42 --encoding={s,S,b,l,B,L}
43 -e {s,S,b,l,B,L}
44 Select character encoding: 7-bit-character, 8-bit-character,
45 bigendian 16-bit, littleendian 16-bit, bigendian 32-bit,
46 littleendian 32-bit.
48 --target=BFDNAME
49 -T {bfdname}
50 Specify a non-default object file format.
52 --help
53 -h Print the usage message on the standard output.
55 --version
56 -v Print the program version number.
58 Written by Richard Stallman <rms@gnu.ai.mit.edu>
59 and David MacKenzie <djm@gnu.ai.mit.edu>. */
61 #include "sysdep.h"
62 #include "bfd.h"
63 #include "getopt.h"
64 #include "libiberty.h"
65 #include "safe-ctype.h"
66 #include <sys/stat.h>
67 #include "bucomm.h"
69 /* Some platforms need to put stdin into binary mode, to read
70 binary files. */
71 #ifdef HAVE_SETMODE
72 #ifndef O_BINARY
73 #ifdef _O_BINARY
74 #define O_BINARY _O_BINARY
75 #define setmode _setmode
76 #else
77 #define O_BINARY 0
78 #endif
79 #endif
80 #if O_BINARY
81 #include <io.h>
82 #define SET_BINARY(f) do { if (!isatty (f)) setmode (f,O_BINARY); } while (0)
83 #endif
84 #endif
86 #define STRING_ISGRAPHIC(c) \
87 ( (c) >= 0 \
88 && (c) <= 255 \
89 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
91 #ifndef errno
92 extern int errno;
93 #endif
95 /* The BFD section flags that identify an initialized data section. */
96 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
98 #ifdef HAVE_FOPEN64
99 typedef off64_t file_off;
100 #define file_open(s,m) fopen64(s, m)
101 #else
102 typedef off_t file_off;
103 #define file_open(s,m) fopen(s, m)
104 #endif
105 #ifdef HAVE_STAT64
106 typedef struct stat64 statbuf;
107 #define file_stat(f,s) stat64(f, s)
108 #else
109 typedef struct stat statbuf;
110 #define file_stat(f,s) stat(f, s)
111 #endif
113 /* Radix for printing addresses (must be 8, 10 or 16). */
114 static int address_radix;
116 /* Minimum length of sequence of graphic chars to trigger output. */
117 static int string_min;
119 /* TRUE means print address within file for each string. */
120 static bfd_boolean print_addresses;
122 /* TRUE means print filename for each string. */
123 static bfd_boolean print_filenames;
125 /* TRUE means for object files scan only the data section. */
126 static bfd_boolean datasection_only;
128 /* TRUE if we found an initialized data section in the current file. */
129 static bfd_boolean got_a_section;
131 /* The BFD object file format. */
132 static char *target;
134 /* The character encoding format. */
135 static char encoding;
136 static int encoding_bytes;
138 static struct option long_options[] =
140 {"all", no_argument, NULL, 'a'},
141 {"print-file-name", no_argument, NULL, 'f'},
142 {"bytes", required_argument, NULL, 'n'},
143 {"radix", required_argument, NULL, 't'},
144 {"encoding", required_argument, NULL, 'e'},
145 {"target", required_argument, NULL, 'T'},
146 {"help", no_argument, NULL, 'h'},
147 {"version", no_argument, NULL, 'v'},
148 {NULL, 0, NULL, 0}
151 /* Records the size of a named file so that we
152 do not repeatedly run bfd_stat() on it. */
154 typedef struct
156 const char * filename;
157 bfd_size_type filesize;
158 } filename_and_size_t;
160 static void strings_a_section (bfd *, asection *, void *);
161 static bfd_boolean strings_object_file (const char *);
162 static bfd_boolean strings_file (char *file);
163 static void print_strings (const char *, FILE *, file_off, int, int, char *);
164 static void usage (FILE *, int);
165 static long get_char (FILE *, file_off *, int *, char **);
167 int main (int, char **);
170 main (int argc, char **argv)
172 int optc;
173 int exit_status = 0;
174 bfd_boolean files_given = FALSE;
176 #if defined (HAVE_SETLOCALE)
177 setlocale (LC_ALL, "");
178 #endif
179 bindtextdomain (PACKAGE, LOCALEDIR);
180 textdomain (PACKAGE);
182 program_name = argv[0];
183 xmalloc_set_program_name (program_name);
185 expandargv (&argc, &argv);
187 string_min = 4;
188 print_addresses = FALSE;
189 print_filenames = FALSE;
190 datasection_only = TRUE;
191 target = NULL;
192 encoding = 's';
194 while ((optc = getopt_long (argc, argv, "afhHn:ot:e:T:Vv0123456789",
195 long_options, (int *) 0)) != EOF)
197 switch (optc)
199 case 'a':
200 datasection_only = FALSE;
201 break;
203 case 'f':
204 print_filenames = TRUE;
205 break;
207 case 'H':
208 case 'h':
209 usage (stdout, 0);
211 case 'n':
212 string_min = (int) strtoul (optarg, NULL, 0);
213 break;
215 case 'o':
216 print_addresses = TRUE;
217 address_radix = 8;
218 break;
220 case 't':
221 print_addresses = TRUE;
222 if (optarg[1] != '\0')
223 usage (stderr, 1);
224 switch (optarg[0])
226 case 'o':
227 address_radix = 8;
228 break;
230 case 'd':
231 address_radix = 10;
232 break;
234 case 'x':
235 address_radix = 16;
236 break;
238 default:
239 usage (stderr, 1);
241 break;
243 case 'T':
244 target = optarg;
245 break;
247 case 'e':
248 if (optarg[1] != '\0')
249 usage (stderr, 1);
250 encoding = optarg[0];
251 break;
253 case 'V':
254 case 'v':
255 print_version ("strings");
256 break;
258 case '?':
259 usage (stderr, 1);
261 default:
262 string_min = (int) strtoul (argv[optind - 1] + 1, NULL, 0);
263 break;
267 if (string_min < 1)
268 fatal (_("invalid minimum string length %d"), string_min);
270 switch (encoding)
272 case 'S':
273 case 's':
274 encoding_bytes = 1;
275 break;
276 case 'b':
277 case 'l':
278 encoding_bytes = 2;
279 break;
280 case 'B':
281 case 'L':
282 encoding_bytes = 4;
283 break;
284 default:
285 usage (stderr, 1);
288 bfd_init ();
289 set_default_bfd_target ();
291 if (optind >= argc)
293 datasection_only = FALSE;
294 #ifdef SET_BINARY
295 SET_BINARY (fileno (stdin));
296 #endif
297 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
298 files_given = TRUE;
300 else
302 for (; optind < argc; ++optind)
304 if (strcmp (argv[optind], "-") == 0)
305 datasection_only = FALSE;
306 else
308 files_given = TRUE;
309 exit_status |= strings_file (argv[optind]) == FALSE;
314 if (!files_given)
315 usage (stderr, 1);
317 return (exit_status);
320 /* Scan section SECT of the file ABFD, whose printable name is in
321 ARG->filename and whose size might be in ARG->filesize. If it
322 contains initialized data set `got_a_section' and print the
323 strings in it.
325 FIXME: We ought to be able to return error codes/messages for
326 certain conditions. */
328 static void
329 strings_a_section (bfd *abfd, asection *sect, void *arg)
331 filename_and_size_t * filename_and_sizep;
332 bfd_size_type *filesizep;
333 bfd_size_type sectsize;
334 void *mem;
336 if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
337 return;
339 sectsize = bfd_get_section_size (sect);
341 if (sectsize <= 0)
342 return;
344 /* Get the size of the file. This might have been cached for us. */
345 filename_and_sizep = (filename_and_size_t *) arg;
346 filesizep = & filename_and_sizep->filesize;
348 if (*filesizep == 0)
350 struct stat st;
352 if (bfd_stat (abfd, &st))
353 return;
355 /* Cache the result so that we do not repeatedly stat this file. */
356 *filesizep = st.st_size;
359 /* Compare the size of the section against the size of the file.
360 If the section is bigger then the file must be corrupt and
361 we should not try dumping it. */
362 if (sectsize >= *filesizep)
363 return;
365 mem = xmalloc (sectsize);
367 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
369 got_a_section = TRUE;
371 print_strings (filename_and_sizep->filename, NULL, sect->filepos,
372 0, sectsize, mem);
375 free (mem);
378 /* Scan all of the sections in FILE, and print the strings
379 in the initialized data section(s).
381 Return TRUE if successful,
382 FALSE if not (such as if FILE is not an object file). */
384 static bfd_boolean
385 strings_object_file (const char *file)
387 filename_and_size_t filename_and_size;
388 bfd *abfd;
390 abfd = bfd_openr (file, target);
392 if (abfd == NULL)
393 /* Treat the file as a non-object file. */
394 return FALSE;
396 /* This call is mainly for its side effect of reading in the sections.
397 We follow the traditional behavior of `strings' in that we don't
398 complain if we don't recognize a file to be an object file. */
399 if (!bfd_check_format (abfd, bfd_object))
401 bfd_close (abfd);
402 return FALSE;
405 got_a_section = FALSE;
406 filename_and_size.filename = file;
407 filename_and_size.filesize = 0;
408 bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
410 if (!bfd_close (abfd))
412 bfd_nonfatal (file);
413 return FALSE;
416 return got_a_section;
419 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
421 static bfd_boolean
422 strings_file (char *file)
424 statbuf st;
426 if (file_stat (file, &st) < 0)
428 if (errno == ENOENT)
429 non_fatal (_("'%s': No such file"), file);
430 else
431 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
432 file, strerror (errno));
433 return FALSE;
436 /* If we weren't told to scan the whole file,
437 try to open it as an object file and only look at
438 initialized data sections. If that fails, fall back to the
439 whole file. */
440 if (!datasection_only || !strings_object_file (file))
442 FILE *stream;
444 stream = file_open (file, FOPEN_RB);
445 if (stream == NULL)
447 fprintf (stderr, "%s: ", program_name);
448 perror (file);
449 return FALSE;
452 print_strings (file, stream, (file_off) 0, 0, 0, (char *) 0);
454 if (fclose (stream) == EOF)
456 fprintf (stderr, "%s: ", program_name);
457 perror (file);
458 return FALSE;
462 return TRUE;
465 /* Read the next character, return EOF if none available.
466 Assume that STREAM is positioned so that the next byte read
467 is at address ADDRESS in the file.
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. */
475 static long
476 get_char (FILE *stream, file_off *address, int *magiccount, char **magic)
478 int c, i;
479 long r = EOF;
480 unsigned char buf[4];
482 for (i = 0; i < encoding_bytes; i++)
484 if (*magiccount)
486 (*magiccount)--;
487 c = *(*magic)++;
489 else
491 if (stream == NULL)
492 return EOF;
494 /* Only use getc_unlocked if we found a declaration for it.
495 Otherwise, libc is not thread safe by default, and we
496 should not use it. */
498 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
499 c = getc_unlocked (stream);
500 #else
501 c = getc (stream);
502 #endif
503 if (c == EOF)
504 return EOF;
507 (*address)++;
508 buf[i] = c;
511 switch (encoding)
513 case 'S':
514 case 's':
515 r = buf[0];
516 break;
517 case 'b':
518 r = (buf[0] << 8) | buf[1];
519 break;
520 case 'l':
521 r = buf[0] | (buf[1] << 8);
522 break;
523 case 'B':
524 r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
525 ((long) buf[2] << 8) | buf[3];
526 break;
527 case 'L':
528 r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
529 ((long) buf[3] << 24);
530 break;
533 if (r == EOF)
534 return 0;
536 return r;
539 /* Find the strings in file FILENAME, read from STREAM.
540 Assume that STREAM is positioned so that the next byte read
541 is at address ADDRESS in the file.
542 Stop reading at address STOP_POINT in the file, if nonzero.
544 If STREAM is NULL, do not read from it.
545 The caller can supply a buffer of characters
546 to be processed before the data in STREAM.
547 MAGIC is the address of the buffer and
548 MAGICCOUNT is how many characters are in it.
549 Those characters come at address ADDRESS and the data in STREAM follow. */
551 static void
552 print_strings (const char *filename, FILE *stream, file_off address,
553 int stop_point, int magiccount, char *magic)
555 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
557 while (1)
559 file_off start;
560 int i;
561 long c;
563 /* See if the next `string_min' chars are all graphic chars. */
564 tryline:
565 if (stop_point && address >= stop_point)
566 break;
567 start = address;
568 for (i = 0; i < string_min; i++)
570 c = get_char (stream, &address, &magiccount, &magic);
571 if (c == EOF)
572 return;
573 if (! STRING_ISGRAPHIC (c))
574 /* Found a non-graphic. Try again starting with next char. */
575 goto tryline;
576 buf[i] = c;
579 /* We found a run of `string_min' graphic characters. Print up
580 to the next non-graphic character. */
582 if (print_filenames)
583 printf ("%s: ", filename);
584 if (print_addresses)
585 switch (address_radix)
587 case 8:
588 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
589 if (sizeof (start) > sizeof (long))
591 #ifndef __MSVCRT__
592 printf ("%7llo ", (unsigned long long) start);
593 #else
594 printf ("%7I64o ", (unsigned long long) start);
595 #endif
597 else
598 #elif !BFD_HOST_64BIT_LONG
599 if (start != (unsigned long) start)
600 printf ("++%7lo ", (unsigned long) start);
601 else
602 #endif
603 printf ("%7lo ", (unsigned long) start);
604 break;
606 case 10:
607 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
608 if (sizeof (start) > sizeof (long))
610 #ifndef __MSVCRT__
611 printf ("%7lld ", (unsigned long long) start);
612 #else
613 printf ("%7I64d ", (unsigned long long) start);
614 #endif
616 else
617 #elif !BFD_HOST_64BIT_LONG
618 if (start != (unsigned long) start)
619 printf ("++%7ld ", (unsigned long) start);
620 else
621 #endif
622 printf ("%7ld ", (long) start);
623 break;
625 case 16:
626 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
627 if (sizeof (start) > sizeof (long))
629 #ifndef __MSVCRT__
630 printf ("%7llx ", (unsigned long long) start);
631 #else
632 printf ("%7I64x ", (unsigned long long) start);
633 #endif
635 else
636 #elif !BFD_HOST_64BIT_LONG
637 if (start != (unsigned long) start)
638 printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
639 (unsigned long) (start & 0xffffffff));
640 else
641 #endif
642 printf ("%7lx ", (unsigned long) start);
643 break;
646 buf[i] = '\0';
647 fputs (buf, stdout);
649 while (1)
651 c = get_char (stream, &address, &magiccount, &magic);
652 if (c == EOF)
653 break;
654 if (! STRING_ISGRAPHIC (c))
655 break;
656 putchar (c);
659 putchar ('\n');
663 static void
664 usage (FILE *stream, int status)
666 fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
667 fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
668 fprintf (stream, _(" The options are:\n\
669 -a - --all Scan the entire file, not just the data section\n\
670 -f --print-file-name Print the name of the file before each string\n\
671 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
672 -<number> least [number] characters (default 4).\n\
673 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
674 -o An alias for --radix=o\n\
675 -T --target=<BFDNAME> Specify the binary file format\n\
676 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
677 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
678 @<file> Read options from <file>\n\
679 -h --help Display this information\n\
680 -v --version Print the program's version number\n"));
681 list_supported_targets (program_name, stream);
682 if (REPORT_BUGS_TO[0] && status == 0)
683 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
684 exit (status);