binutils/
[deliverable/binutils-gdb.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 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 /* Radix for printing addresses (must be 8, 10 or 16). */
84 static int address_radix;
85
86 /* Minimum length of sequence of graphic chars to trigger output. */
87 static int string_min;
88
89 /* TRUE means print address within file for each string. */
90 static bfd_boolean print_addresses;
91
92 /* TRUE means print filename for each string. */
93 static bfd_boolean print_filenames;
94
95 /* TRUE means for object files scan only the data section. */
96 static bfd_boolean datasection_only;
97
98 /* TRUE if we found an initialized data section in the current file. */
99 static bfd_boolean got_a_section;
100
101 /* The BFD object file format. */
102 static char *target;
103
104 /* The character encoding format. */
105 static char encoding;
106 static int encoding_bytes;
107
108 static struct option long_options[] =
109 {
110 {"all", no_argument, NULL, 'a'},
111 {"print-file-name", no_argument, NULL, 'f'},
112 {"bytes", required_argument, NULL, 'n'},
113 {"radix", required_argument, NULL, 't'},
114 {"encoding", required_argument, NULL, 'e'},
115 {"target", required_argument, NULL, 'T'},
116 {"help", no_argument, NULL, 'h'},
117 {"version", no_argument, NULL, 'v'},
118 {NULL, 0, NULL, 0}
119 };
120
121 /* Records the size of a named file so that we
122 do not repeatedly run bfd_stat() on it. */
123
124 typedef struct
125 {
126 const char * filename;
127 bfd_size_type filesize;
128 } filename_and_size_t;
129
130 static void strings_a_section (bfd *, asection *, void *);
131 static bfd_boolean strings_object_file (const char *);
132 static bfd_boolean strings_file (char *file);
133 static void print_strings (const char *, FILE *, file_ptr, int, int, char *);
134 static void usage (FILE *, int);
135 static long get_char (FILE *, file_ptr *, int *, char **);
136 \f
137 int main (int, char **);
138
139 int
140 main (int argc, char **argv)
141 {
142 int optc;
143 int exit_status = 0;
144 bfd_boolean files_given = FALSE;
145 char *s;
146 int numeric_opt = 0;
147
148 #if defined (HAVE_SETLOCALE)
149 setlocale (LC_ALL, "");
150 #endif
151 bindtextdomain (PACKAGE, LOCALEDIR);
152 textdomain (PACKAGE);
153
154 program_name = argv[0];
155 xmalloc_set_program_name (program_name);
156
157 expandargv (&argc, &argv);
158
159 string_min = 4;
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, "afhHn:ot:e:T:Vv0123456789",
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 case 'h':
181 usage (stdout, 0);
182
183 case 'n':
184 string_min = (int) strtoul (optarg, &s, 0);
185 if (s != NULL && *s != 0)
186 fatal (_("invalid integer argument %s"), optarg);
187 break;
188
189 case 'o':
190 print_addresses = TRUE;
191 address_radix = 8;
192 break;
193
194 case 't':
195 print_addresses = TRUE;
196 if (optarg[1] != '\0')
197 usage (stderr, 1);
198 switch (optarg[0])
199 {
200 case 'o':
201 address_radix = 8;
202 break;
203
204 case 'd':
205 address_radix = 10;
206 break;
207
208 case 'x':
209 address_radix = 16;
210 break;
211
212 default:
213 usage (stderr, 1);
214 }
215 break;
216
217 case 'T':
218 target = optarg;
219 break;
220
221 case 'e':
222 if (optarg[1] != '\0')
223 usage (stderr, 1);
224 encoding = optarg[0];
225 break;
226
227 case 'V':
228 case 'v':
229 print_version ("strings");
230 break;
231
232 case '?':
233 usage (stderr, 1);
234
235 default:
236 numeric_opt = optind;
237 break;
238 }
239 }
240
241 if (numeric_opt != 0)
242 {
243 string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0);
244 if (s != NULL && *s != 0)
245 fatal (_("invalid integer argument %s"), argv[numeric_opt - 1] + 1);
246 }
247 if (string_min < 1)
248 fatal (_("invalid minimum string length %d"), string_min);
249
250 switch (encoding)
251 {
252 case 'S':
253 case 's':
254 encoding_bytes = 1;
255 break;
256 case 'b':
257 case 'l':
258 encoding_bytes = 2;
259 break;
260 case 'B':
261 case 'L':
262 encoding_bytes = 4;
263 break;
264 default:
265 usage (stderr, 1);
266 }
267
268 bfd_init ();
269 set_default_bfd_target ();
270
271 if (optind >= argc)
272 {
273 datasection_only = FALSE;
274 SET_BINARY (fileno (stdin));
275 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
276 files_given = TRUE;
277 }
278 else
279 {
280 for (; optind < argc; ++optind)
281 {
282 if (strcmp (argv[optind], "-") == 0)
283 datasection_only = FALSE;
284 else
285 {
286 files_given = TRUE;
287 exit_status |= strings_file (argv[optind]) == FALSE;
288 }
289 }
290 }
291
292 if (!files_given)
293 usage (stderr, 1);
294
295 return (exit_status);
296 }
297 \f
298 /* Scan section SECT of the file ABFD, whose printable name is in
299 ARG->filename and whose size might be in ARG->filesize. If it
300 contains initialized data set `got_a_section' and print the
301 strings in it.
302
303 FIXME: We ought to be able to return error codes/messages for
304 certain conditions. */
305
306 static void
307 strings_a_section (bfd *abfd, asection *sect, void *arg)
308 {
309 filename_and_size_t * filename_and_sizep;
310 bfd_size_type *filesizep;
311 bfd_size_type sectsize;
312 void *mem;
313
314 if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
315 return;
316
317 sectsize = bfd_get_section_size (sect);
318
319 if (sectsize <= 0)
320 return;
321
322 /* Get the size of the file. This might have been cached for us. */
323 filename_and_sizep = (filename_and_size_t *) arg;
324 filesizep = & filename_and_sizep->filesize;
325
326 if (*filesizep == 0)
327 {
328 struct stat st;
329
330 if (bfd_stat (abfd, &st))
331 return;
332
333 /* Cache the result so that we do not repeatedly stat this file. */
334 *filesizep = st.st_size;
335 }
336
337 /* Compare the size of the section against the size of the file.
338 If the section is bigger then the file must be corrupt and
339 we should not try dumping it. */
340 if (sectsize >= *filesizep)
341 return;
342
343 mem = xmalloc (sectsize);
344
345 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
346 {
347 got_a_section = TRUE;
348
349 print_strings (filename_and_sizep->filename, NULL, sect->filepos,
350 0, sectsize, (char *) mem);
351 }
352
353 free (mem);
354 }
355
356 /* Scan all of the sections in FILE, and print the strings
357 in the initialized data section(s).
358
359 Return TRUE if successful,
360 FALSE if not (such as if FILE is not an object file). */
361
362 static bfd_boolean
363 strings_object_file (const char *file)
364 {
365 filename_and_size_t filename_and_size;
366 bfd *abfd;
367
368 abfd = bfd_openr (file, target);
369
370 if (abfd == NULL)
371 /* Treat the file as a non-object file. */
372 return FALSE;
373
374 /* This call is mainly for its side effect of reading in the sections.
375 We follow the traditional behavior of `strings' in that we don't
376 complain if we don't recognize a file to be an object file. */
377 if (!bfd_check_format (abfd, bfd_object))
378 {
379 bfd_close (abfd);
380 return FALSE;
381 }
382
383 got_a_section = FALSE;
384 filename_and_size.filename = file;
385 filename_and_size.filesize = 0;
386 bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
387
388 if (!bfd_close (abfd))
389 {
390 bfd_nonfatal (file);
391 return FALSE;
392 }
393
394 return got_a_section;
395 }
396
397 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
398
399 static bfd_boolean
400 strings_file (char *file)
401 {
402 struct stat st;
403
404 /* get_file_size does not support non-S_ISREG files. */
405
406 if (stat (file, &st) < 0)
407 {
408 if (errno == ENOENT)
409 non_fatal (_("'%s': No such file"), file);
410 else
411 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
412 file, strerror (errno));
413 return FALSE;
414 }
415
416 /* If we weren't told to scan the whole file,
417 try to open it as an object file and only look at
418 initialized data sections. If that fails, fall back to the
419 whole file. */
420 if (!datasection_only || !strings_object_file (file))
421 {
422 FILE *stream;
423
424 stream = fopen (file, FOPEN_RB);
425 if (stream == NULL)
426 {
427 fprintf (stderr, "%s: ", program_name);
428 perror (file);
429 return FALSE;
430 }
431
432 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
433
434 if (fclose (stream) == EOF)
435 {
436 fprintf (stderr, "%s: ", program_name);
437 perror (file);
438 return FALSE;
439 }
440 }
441
442 return TRUE;
443 }
444 \f
445 /* Read the next character, return EOF if none available.
446 Assume that STREAM is positioned so that the next byte read
447 is at address ADDRESS in the file.
448
449 If STREAM is NULL, do not read from it.
450 The caller can supply a buffer of characters
451 to be processed before the data in STREAM.
452 MAGIC is the address of the buffer and
453 MAGICCOUNT is how many characters are in it. */
454
455 static long
456 get_char (FILE *stream, file_ptr *address, int *magiccount, char **magic)
457 {
458 int c, i;
459 long r = EOF;
460 unsigned char buf[4];
461
462 for (i = 0; i < encoding_bytes; i++)
463 {
464 if (*magiccount)
465 {
466 (*magiccount)--;
467 c = *(*magic)++;
468 }
469 else
470 {
471 if (stream == NULL)
472 return EOF;
473
474 /* Only use getc_unlocked if we found a declaration for it.
475 Otherwise, libc is not thread safe by default, and we
476 should not use it. */
477
478 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
479 c = getc_unlocked (stream);
480 #else
481 c = getc (stream);
482 #endif
483 if (c == EOF)
484 return EOF;
485 }
486
487 (*address)++;
488 buf[i] = c;
489 }
490
491 switch (encoding)
492 {
493 case 'S':
494 case 's':
495 r = buf[0];
496 break;
497 case 'b':
498 r = (buf[0] << 8) | buf[1];
499 break;
500 case 'l':
501 r = buf[0] | (buf[1] << 8);
502 break;
503 case 'B':
504 r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
505 ((long) buf[2] << 8) | buf[3];
506 break;
507 case 'L':
508 r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
509 ((long) buf[3] << 24);
510 break;
511 }
512
513 if (r == EOF)
514 return 0;
515
516 return r;
517 }
518 \f
519 /* Find the strings in file FILENAME, read from STREAM.
520 Assume that STREAM is positioned so that the next byte read
521 is at address ADDRESS in the file.
522 Stop reading at address STOP_POINT in the file, if nonzero.
523
524 If STREAM is NULL, do not read from it.
525 The caller can supply a buffer of characters
526 to be processed before the data in STREAM.
527 MAGIC is the address of the buffer and
528 MAGICCOUNT is how many characters are in it.
529 Those characters come at address ADDRESS and the data in STREAM follow. */
530
531 static void
532 print_strings (const char *filename, FILE *stream, file_ptr address,
533 int stop_point, int magiccount, char *magic)
534 {
535 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
536
537 while (1)
538 {
539 file_ptr start;
540 int i;
541 long c;
542
543 /* See if the next `string_min' chars are all graphic chars. */
544 tryline:
545 if (stop_point && address >= stop_point)
546 break;
547 start = address;
548 for (i = 0; i < string_min; i++)
549 {
550 c = get_char (stream, &address, &magiccount, &magic);
551 if (c == EOF)
552 return;
553 if (! STRING_ISGRAPHIC (c))
554 /* Found a non-graphic. Try again starting with next char. */
555 goto tryline;
556 buf[i] = c;
557 }
558
559 /* We found a run of `string_min' graphic characters. Print up
560 to the next non-graphic character. */
561
562 if (print_filenames)
563 printf ("%s: ", filename);
564 if (print_addresses)
565 switch (address_radix)
566 {
567 case 8:
568 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
569 if (sizeof (start) > sizeof (long))
570 {
571 #ifndef __MSVCRT__
572 printf ("%7llo ", (unsigned long long) start);
573 #else
574 printf ("%7I64o ", (unsigned long long) start);
575 #endif
576 }
577 else
578 #elif !BFD_HOST_64BIT_LONG
579 if (start != (unsigned long) start)
580 printf ("++%7lo ", (unsigned long) start);
581 else
582 #endif
583 printf ("%7lo ", (unsigned long) start);
584 break;
585
586 case 10:
587 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
588 if (sizeof (start) > sizeof (long))
589 {
590 #ifndef __MSVCRT__
591 printf ("%7lld ", (unsigned long long) start);
592 #else
593 printf ("%7I64d ", (unsigned long long) start);
594 #endif
595 }
596 else
597 #elif !BFD_HOST_64BIT_LONG
598 if (start != (unsigned long) start)
599 printf ("++%7ld ", (unsigned long) start);
600 else
601 #endif
602 printf ("%7ld ", (long) start);
603 break;
604
605 case 16:
606 #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
607 if (sizeof (start) > sizeof (long))
608 {
609 #ifndef __MSVCRT__
610 printf ("%7llx ", (unsigned long long) start);
611 #else
612 printf ("%7I64x ", (unsigned long long) start);
613 #endif
614 }
615 else
616 #elif !BFD_HOST_64BIT_LONG
617 if (start != (unsigned long) start)
618 printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
619 (unsigned long) (start & 0xffffffff));
620 else
621 #endif
622 printf ("%7lx ", (unsigned long) start);
623 break;
624 }
625
626 buf[i] = '\0';
627 fputs (buf, stdout);
628
629 while (1)
630 {
631 c = get_char (stream, &address, &magiccount, &magic);
632 if (c == EOF)
633 break;
634 if (! STRING_ISGRAPHIC (c))
635 break;
636 putchar (c);
637 }
638
639 putchar ('\n');
640 }
641 }
642 \f
643 static void
644 usage (FILE *stream, int status)
645 {
646 fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
647 fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
648 fprintf (stream, _(" The options are:\n\
649 -a - --all Scan the entire file, not just the data section\n\
650 -f --print-file-name Print the name of the file before each string\n\
651 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
652 -<number> least [number] characters (default 4).\n\
653 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
654 -o An alias for --radix=o\n\
655 -T --target=<BFDNAME> Specify the binary file format\n\
656 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
657 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
658 @<file> Read options from <file>\n\
659 -h --help Display this information\n\
660 -v -V --version Print the program's version number\n"));
661 list_supported_targets (program_name, stream);
662 if (REPORT_BUGS_TO[0] && status == 0)
663 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
664 exit (status);
665 }
This page took 0.044068 seconds and 5 git commands to generate.