2009-05-28 Nick Clifton <nickc@redhat.com>
[binutils.git] / binutils / strings.c
blobdc582f56d00ff2866167eecc6f9799e7843ba34e
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.
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.
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.
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. */
21 /* Usage: strings [options] file...
23 Options:
24 --all
26 - Do not scan only the initialized data section of object files.
28 --print-file-name
29 -f Print the name of the file before each string.
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.
36 --radix={o,x,d}
37 -t {o,x,d} Print the offset within the file before each string,
38 in octal/hex/decimal.
40 -o Like -to. (Some other implementations have -o like -to,
41 others like -td. We chose one arbitrarily.)
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.
49 --target=BFDNAME
50 -T {bfdname}
51 Specify a non-default object file format.
53 --help
54 -h Print the usage message on the standard output.
56 --version
58 -v Print the program version number.
60 Written by Richard Stallman <rms@gnu.ai.mit.edu>
61 and David MacKenzie <djm@gnu.ai.mit.edu>. */
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"
71 #define STRING_ISGRAPHIC(c) \
72 ( (c) >= 0 \
73 && (c) <= 255 \
74 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
76 #ifndef errno
77 extern int errno;
78 #endif
80 /* The BFD section flags that identify an initialized data section. */
81 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
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
98 /* Radix for printing addresses (must be 8, 10 or 16). */
99 static int address_radix;
101 /* Minimum length of sequence of graphic chars to trigger output. */
102 static int string_min;
104 /* TRUE means print address within file for each string. */
105 static bfd_boolean print_addresses;
107 /* TRUE means print filename for each string. */
108 static bfd_boolean print_filenames;
110 /* TRUE means for object files scan only the data section. */
111 static bfd_boolean datasection_only;
113 /* TRUE if we found an initialized data section in the current file. */
114 static bfd_boolean got_a_section;
116 /* The BFD object file format. */
117 static char *target;
119 /* The character encoding format. */
120 static char encoding;
121 static int encoding_bytes;
123 static struct option long_options[] =
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}
136 /* Records the size of a named file so that we
137 do not repeatedly run bfd_stat() on it. */
139 typedef struct
141 const char * filename;
142 bfd_size_type filesize;
143 } filename_and_size_t;
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 **);
152 int main (int, char **);
155 main (int argc, char **argv)
157 int optc;
158 int exit_status = 0;
159 bfd_boolean files_given = FALSE;
160 char *s;
162 #if defined (HAVE_SETLOCALE)
163 setlocale (LC_ALL, "");
164 #endif
165 bindtextdomain (PACKAGE, LOCALEDIR);
166 textdomain (PACKAGE);
168 program_name = argv[0];
169 xmalloc_set_program_name (program_name);
171 expandargv (&argc, &argv);
173 string_min = 4;
174 print_addresses = FALSE;
175 print_filenames = FALSE;
176 datasection_only = TRUE;
177 target = NULL;
178 encoding = 's';
180 while ((optc = getopt_long (argc, argv, "afhHn:ot:e:T:Vv0123456789",
181 long_options, (int *) 0)) != EOF)
183 switch (optc)
185 case 'a':
186 datasection_only = FALSE;
187 break;
189 case 'f':
190 print_filenames = TRUE;
191 break;
193 case 'H':
194 case 'h':
195 usage (stdout, 0);
197 case 'n':
198 string_min = (int) strtoul (optarg, &s, 0);
199 if (s != NULL && *s != 0)
200 fatal (_("invalid integer argument %s"), optarg);
201 break;
203 case 'o':
204 print_addresses = TRUE;
205 address_radix = 8;
206 break;
208 case 't':
209 print_addresses = TRUE;
210 if (optarg[1] != '\0')
211 usage (stderr, 1);
212 switch (optarg[0])
214 case 'o':
215 address_radix = 8;
216 break;
218 case 'd':
219 address_radix = 10;
220 break;
222 case 'x':
223 address_radix = 16;
224 break;
226 default:
227 usage (stderr, 1);
229 break;
231 case 'T':
232 target = optarg;
233 break;
235 case 'e':
236 if (optarg[1] != '\0')
237 usage (stderr, 1);
238 encoding = optarg[0];
239 break;
241 case 'V':
242 case 'v':
243 print_version ("strings");
244 break;
246 case '?':
247 usage (stderr, 1);
249 default:
250 string_min = (int) strtoul (argv[optind - 1] + 1, &s, 0);
251 if (s != NULL && *s != 0)
252 fatal (_("invalid integer argument %s"), argv[optind - 1] + 1);
253 break;
257 if (string_min < 1)
258 fatal (_("invalid minimum string length %d"), string_min);
260 switch (encoding)
262 case 'S':
263 case 's':
264 encoding_bytes = 1;
265 break;
266 case 'b':
267 case 'l':
268 encoding_bytes = 2;
269 break;
270 case 'B':
271 case 'L':
272 encoding_bytes = 4;
273 break;
274 default:
275 usage (stderr, 1);
278 bfd_init ();
279 set_default_bfd_target ();
281 if (optind >= argc)
283 datasection_only = FALSE;
284 SET_BINARY (fileno (stdin));
285 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
286 files_given = TRUE;
288 else
290 for (; optind < argc; ++optind)
292 if (strcmp (argv[optind], "-") == 0)
293 datasection_only = FALSE;
294 else
296 files_given = TRUE;
297 exit_status |= strings_file (argv[optind]) == FALSE;
302 if (!files_given)
303 usage (stderr, 1);
305 return (exit_status);
308 /* Scan section SECT of the file ABFD, whose printable name is in
309 ARG->filename and whose size might be in ARG->filesize. If it
310 contains initialized data set `got_a_section' and print the
311 strings in it.
313 FIXME: We ought to be able to return error codes/messages for
314 certain conditions. */
316 static void
317 strings_a_section (bfd *abfd, asection *sect, void *arg)
319 filename_and_size_t * filename_and_sizep;
320 bfd_size_type *filesizep;
321 bfd_size_type sectsize;
322 void *mem;
324 if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
325 return;
327 sectsize = bfd_get_section_size (sect);
329 if (sectsize <= 0)
330 return;
332 /* Get the size of the file. This might have been cached for us. */
333 filename_and_sizep = (filename_and_size_t *) arg;
334 filesizep = & filename_and_sizep->filesize;
336 if (*filesizep == 0)
338 struct stat st;
340 if (bfd_stat (abfd, &st))
341 return;
343 /* Cache the result so that we do not repeatedly stat this file. */
344 *filesizep = st.st_size;
347 /* Compare the size of the section against the size of the file.
348 If the section is bigger then the file must be corrupt and
349 we should not try dumping it. */
350 if (sectsize >= *filesizep)
351 return;
353 mem = xmalloc (sectsize);
355 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
357 got_a_section = TRUE;
359 print_strings (filename_and_sizep->filename, NULL, sect->filepos,
360 0, sectsize, mem);
363 free (mem);
366 /* Scan all of the sections in FILE, and print the strings
367 in the initialized data section(s).
369 Return TRUE if successful,
370 FALSE if not (such as if FILE is not an object file). */
372 static bfd_boolean
373 strings_object_file (const char *file)
375 filename_and_size_t filename_and_size;
376 bfd *abfd;
378 abfd = bfd_openr (file, target);
380 if (abfd == NULL)
381 /* Treat the file as a non-object file. */
382 return FALSE;
384 /* This call is mainly for its side effect of reading in the sections.
385 We follow the traditional behavior of `strings' in that we don't
386 complain if we don't recognize a file to be an object file. */
387 if (!bfd_check_format (abfd, bfd_object))
389 bfd_close (abfd);
390 return FALSE;
393 got_a_section = FALSE;
394 filename_and_size.filename = file;
395 filename_and_size.filesize = 0;
396 bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
398 if (!bfd_close (abfd))
400 bfd_nonfatal (file);
401 return FALSE;
404 return got_a_section;
407 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
409 static bfd_boolean
410 strings_file (char *file)
412 statbuf st;
414 if (file_stat (file, &st) < 0)
416 if (errno == ENOENT)
417 non_fatal (_("'%s': No such file"), file);
418 else
419 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
420 file, strerror (errno));
421 return FALSE;
424 /* If we weren't told to scan the whole file,
425 try to open it as an object file and only look at
426 initialized data sections. If that fails, fall back to the
427 whole file. */
428 if (!datasection_only || !strings_object_file (file))
430 FILE *stream;
432 stream = file_open (file, FOPEN_RB);
433 if (stream == NULL)
435 fprintf (stderr, "%s: ", program_name);
436 perror (file);
437 return FALSE;
440 print_strings (file, stream, (file_off) 0, 0, 0, (char *) 0);
442 if (fclose (stream) == EOF)
444 fprintf (stderr, "%s: ", program_name);
445 perror (file);
446 return FALSE;
450 return TRUE;
453 /* Read the next character, return EOF if none available.
454 Assume that STREAM is positioned so that the next byte read
455 is at address ADDRESS in the file.
457 If STREAM is NULL, do not read from it.
458 The caller can supply a buffer of characters
459 to be processed before the data in STREAM.
460 MAGIC is the address of the buffer and
461 MAGICCOUNT is how many characters are in it. */
463 static long
464 get_char (FILE *stream, file_off *address, int *magiccount, char **magic)
466 int c, i;
467 long r = EOF;
468 unsigned char buf[4];
470 for (i = 0; i < encoding_bytes; i++)
472 if (*magiccount)
474 (*magiccount)--;
475 c = *(*magic)++;
477 else
479 if (stream == NULL)
480 return EOF;
482 /* Only use getc_unlocked if we found a declaration for it.
483 Otherwise, libc is not thread safe by default, and we
484 should not use it. */
486 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
487 c = getc_unlocked (stream);
488 #else
489 c = getc (stream);
490 #endif
491 if (c == EOF)
492 return EOF;
495 (*address)++;
496 buf[i] = c;
499 switch (encoding)
501 case 'S':
502 case 's':
503 r = buf[0];
504 break;
505 case 'b':
506 r = (buf[0] << 8) | buf[1];
507 break;
508 case 'l':
509 r = buf[0] | (buf[1] << 8);
510 break;
511 case 'B':
512 r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
513 ((long) buf[2] << 8) | buf[3];
514 break;
515 case 'L':
516 r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
517 ((long) buf[3] << 24);
518 break;
521 if (r == EOF)
522 return 0;
524 return r;
527 /* Find the strings in file FILENAME, read from STREAM.
528 Assume that STREAM is positioned so that the next byte read
529 is at address ADDRESS in the file.
530 Stop reading at address STOP_POINT in the file, if nonzero.
532 If STREAM is NULL, do not read from it.
533 The caller can supply a buffer of characters
534 to be processed before the data in STREAM.
535 MAGIC is the address of the buffer and
536 MAGICCOUNT is how many characters are in it.
537 Those characters come at address ADDRESS and the data in STREAM follow. */
539 static void
540 print_strings (const char *filename, FILE *stream, file_off address,
541 int stop_point, int magiccount, char *magic)
543 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
545 while (1)
547 file_off start;
548 int i;
549 long c;
551 /* See if the next `string_min' chars are all graphic chars. */
552 tryline:
553 if (stop_point && address >= stop_point)
554 break;
555 start = address;
556 for (i = 0; i < string_min; i++)
558 c = get_char (stream, &address, &magiccount, &magic);
559 if (c == EOF)
560 return;
561 if (! STRING_ISGRAPHIC (c))
562 /* Found a non-graphic. Try again starting with next char. */
563 goto tryline;
564 buf[i] = c;
567 /* We found a run of `string_min' graphic characters. Print up
568 to the next non-graphic character. */
570 if (print_filenames)
571 printf ("%s: ", filename);
572 if (print_addresses)
573 switch (address_radix)
575 case 8:
576 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
577 if (sizeof (start) > sizeof (long))
579 #ifndef __MSVCRT__
580 printf ("%7llo ", (unsigned long long) start);
581 #else
582 printf ("%7I64o ", (unsigned long long) start);
583 #endif
585 else
586 #elif !BFD_HOST_64BIT_LONG
587 if (start != (unsigned long) start)
588 printf ("++%7lo ", (unsigned long) start);
589 else
590 #endif
591 printf ("%7lo ", (unsigned long) start);
592 break;
594 case 10:
595 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
596 if (sizeof (start) > sizeof (long))
598 #ifndef __MSVCRT__
599 printf ("%7lld ", (unsigned long long) start);
600 #else
601 printf ("%7I64d ", (unsigned long long) start);
602 #endif
604 else
605 #elif !BFD_HOST_64BIT_LONG
606 if (start != (unsigned long) start)
607 printf ("++%7ld ", (unsigned long) start);
608 else
609 #endif
610 printf ("%7ld ", (long) start);
611 break;
613 case 16:
614 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
615 if (sizeof (start) > sizeof (long))
617 #ifndef __MSVCRT__
618 printf ("%7llx ", (unsigned long long) start);
619 #else
620 printf ("%7I64x ", (unsigned long long) start);
621 #endif
623 else
624 #elif !BFD_HOST_64BIT_LONG
625 if (start != (unsigned long) start)
626 printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
627 (unsigned long) (start & 0xffffffff));
628 else
629 #endif
630 printf ("%7lx ", (unsigned long) start);
631 break;
634 buf[i] = '\0';
635 fputs (buf, stdout);
637 while (1)
639 c = get_char (stream, &address, &magiccount, &magic);
640 if (c == EOF)
641 break;
642 if (! STRING_ISGRAPHIC (c))
643 break;
644 putchar (c);
647 putchar ('\n');
651 static void
652 usage (FILE *stream, int status)
654 fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
655 fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
656 fprintf (stream, _(" The options are:\n\
657 -a - --all Scan the entire file, not just the data section\n\
658 -f --print-file-name Print the name of the file before each string\n\
659 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
660 -<number> least [number] characters (default 4).\n\
661 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
662 -o An alias for --radix=o\n\
663 -T --target=<BFDNAME> Specify the binary file format\n\
664 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
665 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
666 @<file> Read options from <file>\n\
667 -h --help Display this information\n\
668 -v -V --version Print the program's version number\n"));
669 list_supported_targets (program_name, stream);
670 if (REPORT_BUGS_TO[0] && status == 0)
671 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
672 exit (status);