ENABLE_CHECKING in bfd, opcodes, binutils, ld
[deliverable/binutils-gdb.git] / binutils / strings.c
1 /* strings -- print the strings of printable characters in files
2 Copyright (C) 1993-2021 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
17 02110-1301, USA. */
18 \f
19 /* Usage: strings [options] file...
20
21 Options:
22 --all
23 -a
24 - Scan each file in its entirety.
25
26 --data
27 -d Scan only the initialized data section(s) of object files.
28
29 --print-file-name
30 -f Print the name of the file before each string.
31
32 --bytes=min-len
33 -n min-len
34 -min-len Print graphic char sequences, MIN-LEN or more bytes long,
35 that are followed by a NUL or a newline. Default is 4.
36
37 --radix={o,x,d}
38 -t {o,x,d} Print the offset within the file before each string,
39 in octal/hex/decimal.
40
41 --include-all-whitespace
42 -w By default tab and space are the only whitepace included in graphic
43 char sequences. This option considers all of isspace() valid.
44
45 -o Like -to. (Some other implementations have -o like -to,
46 others like -td. We chose one arbitrarily.)
47
48 --encoding={s,S,b,l,B,L}
49 -e {s,S,b,l,B,L}
50 Select character encoding: 7-bit-character, 8-bit-character,
51 bigendian 16-bit, littleendian 16-bit, bigendian 32-bit,
52 littleendian 32-bit.
53
54 --target=BFDNAME
55 -T {bfdname}
56 Specify a non-default object file format.
57
58 --output-separator=sep_string
59 -s sep_string String used to separate parsed strings in output.
60 Default is newline.
61
62 --help
63 -h Print the usage message on the standard output.
64
65 --version
66 -V
67 -v Print the program version number.
68
69 Written by Richard Stallman <rms@gnu.ai.mit.edu>
70 and David MacKenzie <djm@gnu.ai.mit.edu>. */
71
72 #include "sysdep.h"
73 #include "bfd.h"
74 #include "getopt.h"
75 #include "libiberty.h"
76 #include "safe-ctype.h"
77 #include "bucomm.h"
78
79 #define STRING_ISGRAPHIC(c) \
80 ( (c) >= 0 \
81 && (c) <= 255 \
82 && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127) \
83 || (include_all_whitespace && ISSPACE (c))) \
84 )
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 /* Whether or not we include all whitespace as a graphic char. */
100 static bool include_all_whitespace;
101
102 /* TRUE means print address within file for each string. */
103 static bool print_addresses;
104
105 /* TRUE means print filename for each string. */
106 static bool print_filenames;
107
108 /* TRUE means for object files scan only the data section. */
109 static bool datasection_only;
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 /* Output string used to separate parsed strings */
119 static char *output_separator;
120
121 static struct option long_options[] =
122 {
123 {"all", no_argument, NULL, 'a'},
124 {"data", no_argument, NULL, 'd'},
125 {"print-file-name", no_argument, NULL, 'f'},
126 {"bytes", required_argument, NULL, 'n'},
127 {"radix", required_argument, NULL, 't'},
128 {"include-all-whitespace", no_argument, NULL, 'w'},
129 {"encoding", required_argument, NULL, 'e'},
130 {"target", required_argument, NULL, 'T'},
131 {"output-separator", required_argument, NULL, 's'},
132 {"help", no_argument, NULL, 'h'},
133 {"version", no_argument, NULL, 'v'},
134 {NULL, 0, NULL, 0}
135 };
136
137 static bool strings_file (char *);
138 static void print_strings (const char *, FILE *, file_ptr, int, int, char *);
139 static void usage (FILE *, int) ATTRIBUTE_NORETURN;
140 \f
141 int main (int, char **);
142
143 int
144 main (int argc, char **argv)
145 {
146 int optc;
147 int exit_status = 0;
148 bool files_given = false;
149 char *s;
150 int numeric_opt = 0;
151
152 setlocale (LC_ALL, "");
153 bindtextdomain (PACKAGE, LOCALEDIR);
154 textdomain (PACKAGE);
155
156 program_name = argv[0];
157 xmalloc_set_program_name (program_name);
158 bfd_set_error_program_name (program_name);
159
160 expandargv (&argc, &argv);
161
162 string_min = 4;
163 include_all_whitespace = false;
164 print_addresses = false;
165 print_filenames = false;
166 if (DEFAULT_STRINGS_ALL)
167 datasection_only = false;
168 else
169 datasection_only = true;
170 target = NULL;
171 encoding = 's';
172 output_separator = NULL;
173
174 while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:Vv0123456789",
175 long_options, (int *) 0)) != EOF)
176 {
177 switch (optc)
178 {
179 case 'a':
180 datasection_only = false;
181 break;
182
183 case 'd':
184 datasection_only = true;
185 break;
186
187 case 'f':
188 print_filenames = true;
189 break;
190
191 case 'H':
192 case 'h':
193 usage (stdout, 0);
194
195 case 'n':
196 string_min = (int) strtoul (optarg, &s, 0);
197 if (s != NULL && *s != 0)
198 fatal (_("invalid integer argument %s"), optarg);
199 break;
200
201 case 'w':
202 include_all_whitespace = true;
203 break;
204
205 case 'o':
206 print_addresses = true;
207 address_radix = 8;
208 break;
209
210 case 't':
211 print_addresses = true;
212 if (optarg[1] != '\0')
213 usage (stderr, 1);
214 switch (optarg[0])
215 {
216 case 'o':
217 address_radix = 8;
218 break;
219
220 case 'd':
221 address_radix = 10;
222 break;
223
224 case 'x':
225 address_radix = 16;
226 break;
227
228 default:
229 usage (stderr, 1);
230 }
231 break;
232
233 case 'T':
234 target = optarg;
235 break;
236
237 case 'e':
238 if (optarg[1] != '\0')
239 usage (stderr, 1);
240 encoding = optarg[0];
241 break;
242
243 case 's':
244 output_separator = optarg;
245 break;
246
247 case 'V':
248 case 'v':
249 print_version ("strings");
250 break;
251
252 case '?':
253 usage (stderr, 1);
254
255 default:
256 numeric_opt = optind;
257 break;
258 }
259 }
260
261 if (numeric_opt != 0)
262 {
263 string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0);
264 if (s != NULL && *s != 0)
265 fatal (_("invalid integer argument %s"), argv[numeric_opt - 1] + 1);
266 }
267 if (string_min < 1)
268 fatal (_("invalid minimum string length %d"), string_min);
269
270 switch (encoding)
271 {
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);
286 }
287
288 if (bfd_init () != BFD_INIT_MAGIC)
289 fatal (_("fatal error: libbfd ABI mismatch"));
290 set_default_bfd_target ();
291
292 if (optind >= argc)
293 {
294 datasection_only = false;
295 SET_BINARY (fileno (stdin));
296 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
297 files_given = true;
298 }
299 else
300 {
301 for (; optind < argc; ++optind)
302 {
303 if (strcmp (argv[optind], "-") == 0)
304 datasection_only = false;
305 else
306 {
307 files_given = true;
308 exit_status |= !strings_file (argv[optind]);
309 }
310 }
311 }
312
313 if (!files_given)
314 usage (stderr, 1);
315
316 return (exit_status);
317 }
318 \f
319 /* Scan section SECT of the file ABFD, whose printable name is
320 FILENAME. If it contains initialized data set GOT_A_SECTION and
321 print the strings in it. */
322
323 static void
324 strings_a_section (bfd *abfd, asection *sect, const char *filename,
325 bool *got_a_section)
326 {
327 bfd_size_type sectsize;
328 bfd_byte *mem;
329
330 if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
331 return;
332
333 sectsize = bfd_section_size (sect);
334 if (sectsize == 0)
335 return;
336
337 if (!bfd_malloc_and_get_section (abfd, sect, &mem))
338 {
339 non_fatal (_("%s: Reading section %s failed: %s"),
340 filename, sect->name, bfd_errmsg (bfd_get_error ()));
341 return;
342 }
343
344 *got_a_section = true;
345 print_strings (filename, NULL, sect->filepos, 0, sectsize, (char *) mem);
346 free (mem);
347 }
348
349 /* Scan all of the sections in FILE, and print the strings
350 in the initialized data section(s).
351
352 Return TRUE if successful,
353 FALSE if not (such as if FILE is not an object file). */
354
355 static bool
356 strings_object_file (const char *file)
357 {
358 bfd *abfd;
359 asection *s;
360 bool got_a_section;
361
362 abfd = bfd_openr (file, target);
363
364 if (abfd == NULL)
365 /* Treat the file as a non-object file. */
366 return false;
367
368 /* This call is mainly for its side effect of reading in the sections.
369 We follow the traditional behavior of `strings' in that we don't
370 complain if we don't recognize a file to be an object file. */
371 if (!bfd_check_format (abfd, bfd_object))
372 {
373 bfd_close (abfd);
374 return false;
375 }
376
377 got_a_section = false;
378 for (s = abfd->sections; s != NULL; s = s->next)
379 strings_a_section (abfd, s, file, &got_a_section);
380
381 if (!bfd_close (abfd))
382 {
383 bfd_nonfatal (file);
384 return false;
385 }
386
387 return got_a_section;
388 }
389
390 /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
391
392 static bool
393 strings_file (char *file)
394 {
395 struct stat st;
396
397 /* get_file_size does not support non-S_ISREG files. */
398
399 if (stat (file, &st) < 0)
400 {
401 if (errno == ENOENT)
402 non_fatal (_("'%s': No such file"), file);
403 else
404 non_fatal (_("Warning: could not locate '%s'. reason: %s"),
405 file, strerror (errno));
406 return false;
407 }
408 else if (S_ISDIR (st.st_mode))
409 {
410 non_fatal (_("Warning: '%s' is a directory"), file);
411 return false;
412 }
413
414 /* If we weren't told to scan the whole file,
415 try to open it as an object file and only look at
416 initialized data sections. If that fails, fall back to the
417 whole file. */
418 if (!datasection_only || !strings_object_file (file))
419 {
420 FILE *stream;
421
422 stream = fopen (file, FOPEN_RB);
423 if (stream == NULL)
424 {
425 fprintf (stderr, "%s: ", program_name);
426 perror (file);
427 return false;
428 }
429
430 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
431
432 if (fclose (stream) == EOF)
433 {
434 fprintf (stderr, "%s: ", program_name);
435 perror (file);
436 return false;
437 }
438 }
439
440 return true;
441 }
442 \f
443 /* Read the next character, return EOF if none available.
444 Assume that STREAM is positioned so that the next byte read
445 is at address ADDRESS in the file.
446
447 If STREAM is NULL, do not read from it.
448 The caller can supply a buffer of characters
449 to be processed before the data in STREAM.
450 MAGIC is the address of the buffer and
451 MAGICCOUNT is how many characters are in it. */
452
453 static long
454 get_char (FILE *stream, file_ptr *address, int *magiccount, char **magic)
455 {
456 int c, i;
457 long r = 0;
458
459 for (i = 0; i < encoding_bytes; i++)
460 {
461 if (*magiccount)
462 {
463 (*magiccount)--;
464 c = *(*magic)++;
465 }
466 else
467 {
468 if (stream == NULL)
469 return EOF;
470
471 /* Only use getc_unlocked if we found a declaration for it.
472 Otherwise, libc is not thread safe by default, and we
473 should not use it. */
474
475 #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
476 c = getc_unlocked (stream);
477 #else
478 c = getc (stream);
479 #endif
480 if (c == EOF)
481 return EOF;
482 }
483
484 (*address)++;
485 r = (r << 8) | (c & 0xff);
486 }
487
488 switch (encoding)
489 {
490 default:
491 break;
492 case 'l':
493 r = ((r & 0xff) << 8) | ((r & 0xff00) >> 8);
494 break;
495 case 'L':
496 r = (((r & 0xff) << 24) | ((r & 0xff00) << 8)
497 | ((r & 0xff0000) >> 8) | ((r & 0xff000000) >> 24));
498 break;
499 }
500
501 return r;
502 }
503
504 /* Throw away one byte of a (possibly) multi-byte char C, updating
505 address and buffer to suit. */
506
507 static void
508 unget_part_char (long c, file_ptr *address, int *magiccount, char **magic)
509 {
510 static char tmp[4];
511
512 if (encoding_bytes > 1)
513 {
514 *address -= encoding_bytes - 1;
515
516 if (*magiccount == 0)
517 {
518 /* If no magic buffer exists, use temp buffer. */
519 switch (encoding)
520 {
521 default:
522 break;
523 case 'b':
524 tmp[0] = c & 0xff;
525 *magiccount = 1;
526 break;
527 case 'l':
528 tmp[0] = (c >> 8) & 0xff;
529 *magiccount = 1;
530 break;
531 case 'B':
532 tmp[0] = (c >> 16) & 0xff;
533 tmp[1] = (c >> 8) & 0xff;
534 tmp[2] = c & 0xff;
535 *magiccount = 3;
536 break;
537 case 'L':
538 tmp[0] = (c >> 8) & 0xff;
539 tmp[1] = (c >> 16) & 0xff;
540 tmp[2] = (c >> 24) & 0xff;
541 *magiccount = 3;
542 break;
543 }
544 *magic = tmp;
545 }
546 else
547 {
548 /* If magic buffer exists, rewind. */
549 *magic -= encoding_bytes - 1;
550 *magiccount += encoding_bytes - 1;
551 }
552 }
553 }
554 \f
555 /* Find the strings in file FILENAME, read from STREAM.
556 Assume that STREAM is positioned so that the next byte read
557 is at address ADDRESS in the file.
558 Stop reading at address STOP_POINT in the file, if nonzero.
559
560 If STREAM is NULL, do not read from it.
561 The caller can supply a buffer of characters
562 to be processed before the data in STREAM.
563 MAGIC is the address of the buffer and
564 MAGICCOUNT is how many characters are in it.
565 Those characters come at address ADDRESS and the data in STREAM follow. */
566
567 static void
568 print_strings (const char *filename, FILE *stream, file_ptr address,
569 int stop_point, int magiccount, char *magic)
570 {
571 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
572
573 while (1)
574 {
575 file_ptr start;
576 int i;
577 long c;
578
579 /* See if the next `string_min' chars are all graphic chars. */
580 tryline:
581 if (stop_point && address >= stop_point)
582 break;
583 start = address;
584 for (i = 0; i < string_min; i++)
585 {
586 c = get_char (stream, &address, &magiccount, &magic);
587 if (c == EOF)
588 {
589 free (buf);
590 return;
591 }
592
593 if (! STRING_ISGRAPHIC (c))
594 {
595 /* Found a non-graphic. Try again starting with next byte. */
596 unget_part_char (c, &address, &magiccount, &magic);
597 goto tryline;
598 }
599 buf[i] = c;
600 }
601
602 /* We found a run of `string_min' graphic characters. Print up
603 to the next non-graphic character. */
604
605 if (print_filenames)
606 printf ("%s: ", filename);
607 if (print_addresses)
608 switch (address_radix)
609 {
610 case 8:
611 if (sizeof (start) > sizeof (long))
612 {
613 #ifndef __MSVCRT__
614 printf ("%7llo ", (unsigned long long) start);
615 #else
616 printf ("%7I64o ", (unsigned long long) start);
617 #endif
618 }
619 else
620 printf ("%7lo ", (unsigned long) start);
621 break;
622
623 case 10:
624 if (sizeof (start) > sizeof (long))
625 {
626 #ifndef __MSVCRT__
627 printf ("%7llu ", (unsigned long long) start);
628 #else
629 printf ("%7I64d ", (unsigned long long) start);
630 #endif
631 }
632 else
633 printf ("%7ld ", (long) start);
634 break;
635
636 case 16:
637 if (sizeof (start) > sizeof (long))
638 {
639 #ifndef __MSVCRT__
640 printf ("%7llx ", (unsigned long long) start);
641 #else
642 printf ("%7I64x ", (unsigned long long) start);
643 #endif
644 }
645 else
646 printf ("%7lx ", (unsigned long) start);
647 break;
648 }
649
650 buf[i] = '\0';
651 fputs (buf, stdout);
652
653 while (1)
654 {
655 c = get_char (stream, &address, &magiccount, &magic);
656 if (c == EOF)
657 break;
658 if (! STRING_ISGRAPHIC (c))
659 {
660 unget_part_char (c, &address, &magiccount, &magic);
661 break;
662 }
663 putchar (c);
664 }
665
666 if (output_separator)
667 fputs (output_separator, stdout);
668 else
669 putchar ('\n');
670 }
671 free (buf);
672 }
673 \f
674 static void
675 usage (FILE *stream, int status)
676 {
677 fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
678 fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
679 fprintf (stream, _(" The options are:\n"));
680
681 if (DEFAULT_STRINGS_ALL)
682 fprintf (stream, _("\
683 -a - --all Scan the entire file, not just the data section [default]\n\
684 -d --data Only scan the data sections in the file\n"));
685 else
686 fprintf (stream, _("\
687 -a - --all Scan the entire file, not just the data section\n\
688 -d --data Only scan the data sections in the file [default]\n"));
689
690 fprintf (stream, _("\
691 -f --print-file-name Print the name of the file before each string\n\
692 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
693 -<number> least [number] characters (default 4).\n\
694 -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
695 -w --include-all-whitespace Include all whitespace as valid string characters\n\
696 -o An alias for --radix=o\n\
697 -T --target=<BFDNAME> Specify the binary file format\n\
698 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
699 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
700 -s --output-separator=<string> String used to separate strings in output.\n\
701 @<file> Read options from <file>\n\
702 -h --help Display this information\n\
703 -v -V --version Print the program's version number\n"));
704 list_supported_targets (program_name, stream);
705 if (REPORT_BUGS_TO[0] && status == 0)
706 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
707 exit (status);
708 }
This page took 0.05066 seconds and 4 git commands to generate.