2007-01-16 H.J. Lu <hongjiu.lu@intel.com>
[binutils.git] / binutils / strings.c
blob4c68ea8f8c311152e1833f61b5630341cf492dfd
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 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 2, 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 #ifdef HAVE_CONFIG_H
62 #include "config.h"
63 #endif
64 #include "bfd.h"
65 #include <stdio.h>
66 #include "getopt.h"
67 #include <errno.h>
68 #include "bucomm.h"
69 #include "libiberty.h"
70 #include "safe-ctype.h"
71 #include <sys/stat.h>
73 /* Some platforms need to put stdin into binary mode, to read
74 binary files. */
75 #ifdef HAVE_SETMODE
76 #ifndef O_BINARY
77 #ifdef _O_BINARY
78 #define O_BINARY _O_BINARY
79 #define setmode _setmode
80 #else
81 #define O_BINARY 0
82 #endif
83 #endif
84 #if O_BINARY
85 #include <io.h>
86 #define SET_BINARY(f) do { if (!isatty (f)) setmode (f,O_BINARY); } while (0)
87 #endif
88 #endif
90 #define STRING_ISGRAPHIC(c) \
91 ( (c) >= 0 \
92 && (c) <= 255 \
93 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
95 #ifndef errno
96 extern int errno;
97 #endif
99 /* The BFD section flags that identify an initialized data section. */
100 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
102 #ifdef HAVE_FOPEN64
103 typedef off64_t file_off;
104 #define file_open(s,m) fopen64(s, m)
105 #else
106 typedef off_t file_off;
107 #define file_open(s,m) fopen(s, m)
108 #endif
109 #ifdef HAVE_STAT64
110 typedef struct stat64 statbuf;
111 #define file_stat(f,s) stat64(f, s)
112 #else
113 typedef struct stat statbuf;
114 #define file_stat(f,s) stat(f, s)
115 #endif
117 /* Radix for printing addresses (must be 8, 10 or 16). */
118 static int address_radix;
120 /* Minimum length of sequence of graphic chars to trigger output. */
121 static int string_min;
123 /* TRUE means print address within file for each string. */
124 static bfd_boolean print_addresses;
126 /* TRUE means print filename for each string. */
127 static bfd_boolean print_filenames;
129 /* TRUE means for object files scan only the data section. */
130 static bfd_boolean datasection_only;
132 /* TRUE if we found an initialized data section in the current file. */
133 static bfd_boolean got_a_section;
135 /* The BFD object file format. */
136 static char *target;
138 /* The character encoding format. */
139 static char encoding;
140 static int encoding_bytes;
142 static struct option long_options[] =
144 {"all", no_argument, NULL, 'a'},
145 {"print-file-name", no_argument, NULL, 'f'},
146 {"bytes", required_argument, NULL, 'n'},
147 {"radix", required_argument, NULL, 't'},
148 {"encoding", required_argument, NULL, 'e'},
149 {"target", required_argument, NULL, 'T'},
150 {"help", no_argument, NULL, 'h'},
151 {"version", no_argument, NULL, 'v'},
152 {NULL, 0, NULL, 0}
155 /* Records the size of a named file so that we
156 do not repeatedly run bfd_stat() on it. */
158 typedef struct
160 const char * filename;
161 bfd_size_type filesize;
162 } filename_and_size_t;
164 static void strings_a_section (bfd *, asection *, void *);
165 static bfd_boolean strings_object_file (const char *);
166 static bfd_boolean strings_file (char *file);
167 static int integer_arg (char *s);
168 static void print_strings (const char *, FILE *, file_off, int, int, char *);
169 static void usage (FILE *, int);
170 static long get_char (FILE *, file_off *, int *, char **);
172 int main (int, char **);
175 main (int argc, char **argv)
177 int optc;
178 int exit_status = 0;
179 bfd_boolean files_given = FALSE;
181 #if defined (HAVE_SETLOCALE)
182 setlocale (LC_ALL, "");
183 #endif
184 bindtextdomain (PACKAGE, LOCALEDIR);
185 textdomain (PACKAGE);
187 program_name = argv[0];
188 xmalloc_set_program_name (program_name);
190 expandargv (&argc, &argv);
192 string_min = -1;
193 print_addresses = FALSE;
194 print_filenames = FALSE;
195 datasection_only = TRUE;
196 target = NULL;
197 encoding = 's';
199 while ((optc = getopt_long (argc, argv, "afhHn:ot:e:T:Vv0123456789",
200 long_options, (int *) 0)) != EOF)
202 switch (optc)
204 case 'a':
205 datasection_only = FALSE;
206 break;
208 case 'f':
209 print_filenames = TRUE;
210 break;
212 case 'H':
213 case 'h':
214 usage (stdout, 0);
216 case 'n':
217 string_min = integer_arg (optarg);
218 if (string_min < 1)
219 fatal (_("invalid number %s"), optarg);
220 break;
222 case 'o':
223 print_addresses = TRUE;
224 address_radix = 8;
225 break;
227 case 't':
228 print_addresses = TRUE;
229 if (optarg[1] != '\0')
230 usage (stderr, 1);
231 switch (optarg[0])
233 case 'o':
234 address_radix = 8;
235 break;
237 case 'd':
238 address_radix = 10;
239 break;
241 case 'x':
242 address_radix = 16;
243 break;
245 default:
246 usage (stderr, 1);
248 break;
250 case 'T':
251 target = optarg;
252 break;
254 case 'e':
255 if (optarg[1] != '\0')
256 usage (stderr, 1);
257 encoding = optarg[0];
258 break;
260 case 'V':
261 case 'v':
262 print_version ("strings");
263 break;
265 case '?':
266 usage (stderr, 1);
268 default:
269 if (string_min < 0)
270 string_min = optc - '0';
271 else
272 string_min = string_min * 10 + optc - '0';
273 break;
277 if (string_min < 0)
278 string_min = 4;
280 switch (encoding)
282 case 'S':
283 case 's':
284 encoding_bytes = 1;
285 break;
286 case 'b':
287 case 'l':
288 encoding_bytes = 2;
289 break;
290 case 'B':
291 case 'L':
292 encoding_bytes = 4;
293 break;
294 default:
295 usage (stderr, 1);
298 bfd_init ();
299 set_default_bfd_target ();
301 if (optind >= argc)
303 datasection_only = FALSE;
304 #ifdef SET_BINARY
305 SET_BINARY (fileno (stdin));
306 #endif
307 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
308 files_given = TRUE;
310 else
312 for (; optind < argc; ++optind)
314 if (strcmp (argv[optind], "-") == 0)
315 datasection_only = FALSE;
316 else
318 files_given = TRUE;
319 exit_status |= strings_file (argv[optind]) == FALSE;
324 if (!files_given)
325 usage (stderr, 1);
327 return (exit_status);
330 /* Scan section SECT of the file ABFD, whose printable name is in
331 ARG->filename and whose size might be in ARG->filesize. If it
332 contains initialized data set `got_a_section' and print the
333 strings in it.
335 FIXME: We ought to be able to return error codes/messages for
336 certain conditions. */
338 static void
339 strings_a_section (bfd *abfd, asection *sect, void *arg)
341 filename_and_size_t * filename_and_sizep;
342 bfd_size_type *filesizep;
343 bfd_size_type sectsize;
344 void *mem;
346 if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
347 return;
349 sectsize = bfd_get_section_size (sect);
351 if (sectsize <= 0)
352 return;
354 /* Get the size of the file. This might have been cached for us. */
355 filename_and_sizep = (filename_and_size_t *) arg;
356 filesizep = & filename_and_sizep->filesize;
358 if (*filesizep == 0)
360 struct stat st;
362 if (bfd_stat (abfd, &st))
363 return;
365 /* Cache the result so that we do not repeatedly stat this file. */
366 *filesizep = st.st_size;
369 /* Compare the size of the section against the size of the file.
370 If the section is bigger then the file must be corrupt and
371 we should not try dumping it. */
372 if (sectsize >= *filesizep)
373 return;
375 mem = xmalloc (sectsize);
377 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
379 got_a_section = TRUE;
381 print_strings (filename_and_sizep->filename, NULL, sect->filepos,
382 0, sectsize, mem);
385 free (mem);
388 /* Scan all of the sections in FILE, and print the strings
389 in the initialized data section(s).
391 Return TRUE if successful,
392 FALSE if not (such as if FILE is not an object file). */
394 static bfd_boolean
395 strings_object_file (const char *file)
397 filename_and_size_t filename_and_size;
398 bfd *abfd;
400 abfd = bfd_openr (file, target);
402 if (abfd == NULL)
403 /* Treat the file as a non-object file. */
404 return FALSE;
406 /* This call is mainly for its side effect of reading in the sections.
407 We follow the traditional behavior of `strings' in that we don't
408 complain if we don't recognize a file to be an object file. */
409 if (!bfd_check_format (abfd, bfd_object))
411 bfd_close (abfd);
412 return FALSE;
415 got_a_section = FALSE;
416 filename_and_size.filename = file;
417 filename_and_size.filesize = 0;
418 bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
420 if (!bfd_close (abfd))
422 bfd_nonfatal (file);
423 return FALSE;
426 return got_a_section;
429 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
431 static bfd_boolean
432 strings_file (char *file)
434 statbuf st;
436 if (file_stat (file, &st) < 0)
438 if (errno == ENOENT)
439 non_fatal (_("'%s': No such file"), file);
440 else
441 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
442 file, strerror (errno));
443 return FALSE;
446 /* If we weren't told to scan the whole file,
447 try to open it as an object file and only look at
448 initialized data sections. If that fails, fall back to the
449 whole file. */
450 if (!datasection_only || !strings_object_file (file))
452 FILE *stream;
454 stream = file_open (file, FOPEN_RB);
455 if (stream == NULL)
457 fprintf (stderr, "%s: ", program_name);
458 perror (file);
459 return FALSE;
462 print_strings (file, stream, (file_off) 0, 0, 0, (char *) 0);
464 if (fclose (stream) == EOF)
466 fprintf (stderr, "%s: ", program_name);
467 perror (file);
468 return FALSE;
472 return TRUE;
475 /* Read the next character, return EOF if none available.
476 Assume that STREAM is positioned so that the next byte read
477 is at address ADDRESS in the file.
479 If STREAM is NULL, do not read from it.
480 The caller can supply a buffer of characters
481 to be processed before the data in STREAM.
482 MAGIC is the address of the buffer and
483 MAGICCOUNT is how many characters are in it. */
485 static long
486 get_char (FILE *stream, file_off *address, int *magiccount, char **magic)
488 int c, i;
489 long r = EOF;
490 unsigned char buf[4];
492 for (i = 0; i < encoding_bytes; i++)
494 if (*magiccount)
496 (*magiccount)--;
497 c = *(*magic)++;
499 else
501 if (stream == NULL)
502 return EOF;
504 /* Only use getc_unlocked if we found a declaration for it.
505 Otherwise, libc is not thread safe by default, and we
506 should not use it. */
508 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
509 c = getc_unlocked (stream);
510 #else
511 c = getc (stream);
512 #endif
513 if (c == EOF)
514 return EOF;
517 (*address)++;
518 buf[i] = c;
521 switch (encoding)
523 case 'S':
524 case 's':
525 r = buf[0];
526 break;
527 case 'b':
528 r = (buf[0] << 8) | buf[1];
529 break;
530 case 'l':
531 r = buf[0] | (buf[1] << 8);
532 break;
533 case 'B':
534 r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
535 ((long) buf[2] << 8) | buf[3];
536 break;
537 case 'L':
538 r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
539 ((long) buf[3] << 24);
540 break;
543 if (r == EOF)
544 return 0;
546 return r;
549 /* Find the strings in file FILENAME, read from STREAM.
550 Assume that STREAM is positioned so that the next byte read
551 is at address ADDRESS in the file.
552 Stop reading at address STOP_POINT in the file, if nonzero.
554 If STREAM is NULL, do not read from it.
555 The caller can supply a buffer of characters
556 to be processed before the data in STREAM.
557 MAGIC is the address of the buffer and
558 MAGICCOUNT is how many characters are in it.
559 Those characters come at address ADDRESS and the data in STREAM follow. */
561 static void
562 print_strings (const char *filename, FILE *stream, file_off address,
563 int stop_point, int magiccount, char *magic)
565 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
567 while (1)
569 file_off start;
570 int i;
571 long c;
573 /* See if the next `string_min' chars are all graphic chars. */
574 tryline:
575 if (stop_point && address >= stop_point)
576 break;
577 start = address;
578 for (i = 0; i < string_min; i++)
580 c = get_char (stream, &address, &magiccount, &magic);
581 if (c == EOF)
582 return;
583 if (! STRING_ISGRAPHIC (c))
584 /* Found a non-graphic. Try again starting with next char. */
585 goto tryline;
586 buf[i] = c;
589 /* We found a run of `string_min' graphic characters. Print up
590 to the next non-graphic character. */
592 if (print_filenames)
593 printf ("%s: ", filename);
594 if (print_addresses)
595 switch (address_radix)
597 case 8:
598 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
599 if (sizeof (start) > sizeof (long))
600 printf ("%7Lo ", (unsigned long long) start);
601 else
602 #else
603 # if !BFD_HOST_64BIT_LONG
604 if (start != (unsigned long) start)
605 printf ("++%7lo ", (unsigned long) start);
606 else
607 # endif
608 #endif
609 printf ("%7lo ", (unsigned long) start);
610 break;
612 case 10:
613 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
614 if (sizeof (start) > sizeof (long))
615 printf ("%7Ld ", (unsigned long long) start);
616 else
617 #else
618 # if !BFD_HOST_64BIT_LONG
619 if (start != (unsigned long) start)
620 printf ("++%7ld ", (unsigned long) start);
621 else
622 # endif
623 #endif
624 printf ("%7ld ", (long) start);
625 break;
627 case 16:
628 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
629 if (sizeof (start) > sizeof (long))
630 printf ("%7Lx ", (unsigned long long) start);
631 else
632 #else
633 # if !BFD_HOST_64BIT_LONG
634 if (start != (unsigned long) start)
635 printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
636 (unsigned long) (start & 0xffffffff));
637 else
638 # endif
639 #endif
640 printf ("%7lx ", (unsigned long) start);
641 break;
644 buf[i] = '\0';
645 fputs (buf, stdout);
647 while (1)
649 c = get_char (stream, &address, &magiccount, &magic);
650 if (c == EOF)
651 break;
652 if (! STRING_ISGRAPHIC (c))
653 break;
654 putchar (c);
657 putchar ('\n');
661 /* Parse string S as an integer, using decimal radix by default,
662 but allowing octal and hex numbers as in C. */
664 static int
665 integer_arg (char *s)
667 int value;
668 int radix = 10;
669 char *p = s;
670 int c;
672 if (*p != '0')
673 radix = 10;
674 else if (*++p == 'x')
676 radix = 16;
677 p++;
679 else
680 radix = 8;
682 value = 0;
683 while (((c = *p++) >= '0' && c <= '9')
684 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
686 value *= radix;
687 if (c >= '0' && c <= '9')
688 value += c - '0';
689 else
690 value += (c & ~40) - 'A';
693 if (c == 'b')
694 value *= 512;
695 else if (c == 'B')
696 value *= 1024;
697 else
698 p--;
700 if (*p)
701 fatal (_("invalid integer argument %s"), s);
703 return value;
706 static void
707 usage (FILE *stream, int status)
709 fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
710 fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
711 fprintf (stream, _(" The options are:\n\
712 -a - --all Scan the entire file, not just the data section\n\
713 -f --print-file-name Print the name of the file before each string\n\
714 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
715 -<number> least [number] characters (default 4).\n\
716 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
717 -o An alias for --radix=o\n\
718 -T --target=<BFDNAME> Specify the binary file format\n\
719 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
720 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
721 @<file> Read options from <file>\n\
722 -h --help Display this information\n\
723 -v --version Print the program's version number\n"));
724 list_supported_targets (program_name, stream);
725 if (status == 0)
726 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
727 exit (status);