]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - binutils/strings.c
s/boolean/bfd_boolean/ s/true/TRUE/ s/false/FALSE/. Simplify
[thirdparty/binutils-gdb.git] / binutils / strings.c
CommitLineData
252b5132 1/* strings -- print the strings of printable characters in files
8b53311e
NC
2 Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3 2002 Free Software Foundation, Inc.
252b5132
RH
4
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.
9
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.
14
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., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA. */
19\f
20/* Usage: strings [options] file...
21
22 Options:
23 --all
24 -a
25 - Do not scan only the initialized data section of object files.
26
27 --print-file-name
28 -f Print the name of the file before each string.
29
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.
34
35 --radix={o,x,d}
36 -t {o,x,d} Print the offset within the file before each string,
37 in octal/hex/decimal.
38
39 -o Like -to. (Some other implementations have -o like -to,
40 others like -td. We chose one arbitrarily.)
41
d132876a
NC
42 --encoding={s,b,l,B,L}
43 -e {s,b,l,B,L}
44 Select character encoding: single-byte, bigendian 16-bit,
45 littleendian 16-bit, bigendian 32-bit, littleendian 32-bit
46
252b5132
RH
47 --target=BFDNAME
48 Specify a non-default object file format.
49
50 --help
51 -h Print the usage message on the standard output.
52
53 --version
54 -v Print the program version number.
55
56 Written by Richard Stallman <rms@gnu.ai.mit.edu>
57 and David MacKenzie <djm@gnu.ai.mit.edu>. */
58
cedd9a58
JJ
59#ifdef HAVE_CONFIG_H
60#include "config.h"
61#endif
252b5132
RH
62#include "bfd.h"
63#include <stdio.h>
e9792343 64#include "getopt.h"
252b5132
RH
65#include <errno.h>
66#include "bucomm.h"
67#include "libiberty.h"
3882b010 68#include "safe-ctype.h"
252b5132 69
5af11cab
AM
70/* Some platforms need to put stdin into binary mode, to read
71 binary files. */
72#ifdef HAVE_SETMODE
73#ifndef O_BINARY
74#ifdef _O_BINARY
75#define O_BINARY _O_BINARY
76#define setmode _setmode
77#else
78#define O_BINARY 0
79#endif
80#endif
81#if O_BINARY
82#include <io.h>
83#define SET_BINARY(f) do { if (!isatty(f)) setmode(f,O_BINARY); } while (0)
84#endif
85#endif
86
3882b010 87#define isgraphic(c) (ISPRINT (c) || (c) == '\t')
252b5132
RH
88
89#ifndef errno
90extern int errno;
91#endif
92
93/* The BFD section flags that identify an initialized data section. */
94#define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
95
cedd9a58
JJ
96#ifdef HAVE_FOPEN64
97typedef off64_t file_off;
98#define file_open(s,m) fopen64(s,m)
99#else
100typedef off_t file_off;
101#define file_open(s,m) fopen(s,m)
102#endif
103
252b5132
RH
104/* Radix for printing addresses (must be 8, 10 or 16). */
105static int address_radix;
106
107/* Minimum length of sequence of graphic chars to trigger output. */
108static int string_min;
109
b34976b6
AM
110/* TRUE means print address within file for each string. */
111static bfd_boolean print_addresses;
252b5132 112
b34976b6
AM
113/* TRUE means print filename for each string. */
114static bfd_boolean print_filenames;
252b5132 115
b34976b6
AM
116/* TRUE means for object files scan only the data section. */
117static bfd_boolean datasection_only;
252b5132 118
b34976b6
AM
119/* TRUE if we found an initialized data section in the current file. */
120static bfd_boolean got_a_section;
252b5132
RH
121
122/* The BFD object file format. */
123static char *target;
124
d132876a
NC
125/* The character encoding format. */
126static char encoding;
127static int encoding_bytes;
128
252b5132
RH
129static struct option long_options[] =
130{
131 {"all", no_argument, NULL, 'a'},
132 {"print-file-name", no_argument, NULL, 'f'},
133 {"bytes", required_argument, NULL, 'n'},
134 {"radix", required_argument, NULL, 't'},
d132876a 135 {"encoding", required_argument, NULL, 'e'},
252b5132
RH
136 {"target", required_argument, NULL, 'T'},
137 {"help", no_argument, NULL, 'h'},
138 {"version", no_argument, NULL, 'v'},
139 {NULL, 0, NULL, 0}
140};
141
b34976b6
AM
142static void strings_a_section
143 PARAMS ((bfd *, asection *, PTR));
144static bfd_boolean strings_object_file
145 PARAMS ((const char *));
146static bfd_boolean strings_file
147 PARAMS ((char *file));
148static int integer_arg
149 PARAMS ((char *s));
150static void print_strings
151 PARAMS ((const char *filename, FILE *stream, file_off address,
152 int stop_point, int magiccount, char *magic));
153static void usage
154 PARAMS ((FILE *stream, int status));
155static long get_char
156 PARAMS ((FILE *stream, file_off *address, int *magiccount, char **magic));
252b5132 157\f
b34976b6
AM
158int main
159 PARAMS ((int, char **));
65de42c0 160
252b5132
RH
161int
162main (argc, argv)
163 int argc;
164 char **argv;
165{
166 int optc;
167 int exit_status = 0;
b34976b6 168 bfd_boolean files_given = FALSE;
252b5132 169
3882b010 170#if defined (HAVE_SETLOCALE)
1c529ca6 171 setlocale (LC_ALL, "");
252b5132
RH
172#endif
173 bindtextdomain (PACKAGE, LOCALEDIR);
174 textdomain (PACKAGE);
175
176 program_name = argv[0];
177 xmalloc_set_program_name (program_name);
178 string_min = -1;
b34976b6
AM
179 print_addresses = FALSE;
180 print_filenames = FALSE;
181 datasection_only = TRUE;
252b5132 182 target = NULL;
d132876a 183 encoding = 's';
252b5132 184
8b53311e 185 while ((optc = getopt_long (argc, argv, "afhHn:ot:e:Vv0123456789",
252b5132
RH
186 long_options, (int *) 0)) != EOF)
187 {
188 switch (optc)
189 {
190 case 'a':
b34976b6 191 datasection_only = FALSE;
252b5132
RH
192 break;
193
194 case 'f':
b34976b6 195 print_filenames = TRUE;
252b5132
RH
196 break;
197
8b53311e 198 case 'H':
252b5132
RH
199 case 'h':
200 usage (stdout, 0);
201
202 case 'n':
203 string_min = integer_arg (optarg);
204 if (string_min < 1)
205 {
37cc8ec1 206 fatal (_("invalid number %s"), optarg);
252b5132
RH
207 }
208 break;
209
210 case 'o':
b34976b6 211 print_addresses = TRUE;
252b5132
RH
212 address_radix = 8;
213 break;
214
215 case 't':
b34976b6 216 print_addresses = TRUE;
252b5132
RH
217 if (optarg[1] != '\0')
218 usage (stderr, 1);
219 switch (optarg[0])
220 {
221 case 'o':
222 address_radix = 8;
223 break;
224
225 case 'd':
226 address_radix = 10;
227 break;
228
229 case 'x':
230 address_radix = 16;
231 break;
232
233 default:
234 usage (stderr, 1);
235 }
236 break;
237
238 case 'T':
239 target = optarg;
240 break;
241
d132876a
NC
242 case 'e':
243 if (optarg[1] != '\0')
244 usage (stderr, 1);
245 encoding = optarg[0];
246 break;
247
8b53311e 248 case 'V':
252b5132
RH
249 case 'v':
250 print_version ("strings");
251 break;
252
253 case '?':
254 usage (stderr, 1);
255
256 default:
257 if (string_min < 0)
221f77a9 258 string_min = optc - '0';
252b5132
RH
259 else
260 string_min = string_min * 10 + optc - '0';
261 break;
262 }
263 }
264
265 if (string_min < 0)
266 string_min = 4;
267
d132876a
NC
268 switch (encoding)
269 {
270 case 's':
271 encoding_bytes = 1;
272 break;
273 case 'b':
274 case 'l':
275 encoding_bytes = 2;
276 break;
277 case 'B':
278 case 'L':
279 encoding_bytes = 4;
280 break;
281 default:
282 usage (stderr, 1);
283 }
284
252b5132
RH
285 bfd_init ();
286 set_default_bfd_target ();
287
288 if (optind >= argc)
289 {
b34976b6 290 datasection_only = FALSE;
5af11cab
AM
291#ifdef SET_BINARY
292 SET_BINARY (fileno (stdin));
293#endif
252b5132 294 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
b34976b6 295 files_given = TRUE;
252b5132
RH
296 }
297 else
298 {
299 for (; optind < argc; ++optind)
300 {
301 if (strcmp (argv[optind], "-") == 0)
b34976b6 302 datasection_only = FALSE;
252b5132
RH
303 else
304 {
b34976b6
AM
305 files_given = TRUE;
306 exit_status |= strings_file (argv[optind]) == FALSE;
252b5132
RH
307 }
308 }
309 }
310
b34976b6 311 if (!files_given)
252b5132
RH
312 usage (stderr, 1);
313
314 return (exit_status);
315}
316\f
317/* Scan section SECT of the file ABFD, whose printable name is FILE.
318 If it contains initialized data,
319 set `got_a_section' and print the strings in it. */
320
321static void
322strings_a_section (abfd, sect, filearg)
323 bfd *abfd;
324 asection *sect;
325 PTR filearg;
326{
327 const char *file = (const char *) filearg;
328
329 if ((sect->flags & DATA_FLAGS) == DATA_FLAGS)
330 {
331 bfd_size_type sz = bfd_get_section_size_before_reloc (sect);
332 PTR mem = xmalloc (sz);
333 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz))
334 {
b34976b6 335 got_a_section = TRUE;
252b5132
RH
336 print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
337 }
338 free (mem);
339 }
340}
341
342/* Scan all of the sections in FILE, and print the strings
343 in the initialized data section(s).
344
b34976b6
AM
345 Return TRUE if successful,
346 FALSE if not (such as if FILE is not an object file). */
252b5132 347
b34976b6 348static bfd_boolean
252b5132
RH
349strings_object_file (file)
350 const char *file;
351{
352 bfd *abfd = bfd_openr (file, target);
353
354 if (abfd == NULL)
355 {
356 /* Treat the file as a non-object file. */
b34976b6 357 return FALSE;
252b5132
RH
358 }
359
360 /* This call is mainly for its side effect of reading in the sections.
361 We follow the traditional behavior of `strings' in that we don't
362 complain if we don't recognize a file to be an object file. */
b34976b6 363 if (!bfd_check_format (abfd, bfd_object))
252b5132
RH
364 {
365 bfd_close (abfd);
b34976b6 366 return FALSE;
252b5132
RH
367 }
368
b34976b6 369 got_a_section = FALSE;
252b5132
RH
370 bfd_map_over_sections (abfd, strings_a_section, (PTR) file);
371
372 if (!bfd_close (abfd))
373 {
374 bfd_nonfatal (file);
b34976b6 375 return FALSE;
252b5132
RH
376 }
377
378 return got_a_section;
379}
380
b34976b6 381/* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
252b5132 382
b34976b6 383static bfd_boolean
252b5132
RH
384strings_file (file)
385 char *file;
386{
387 /* If we weren't told to scan the whole file,
388 try to open it as an object file and only look at
389 initialized data sections. If that fails, fall back to the
390 whole file. */
391 if (!datasection_only || !strings_object_file (file))
392 {
393 FILE *stream;
394
cedd9a58 395 stream = file_open (file, FOPEN_RB);
252b5132
RH
396 if (stream == NULL)
397 {
398 fprintf (stderr, "%s: ", program_name);
399 perror (file);
b34976b6 400 return FALSE;
252b5132
RH
401 }
402
cedd9a58 403 print_strings (file, stream, (file_off) 0, 0, 0, (char *) 0);
252b5132
RH
404
405 if (fclose (stream) == EOF)
406 {
407 fprintf (stderr, "%s: ", program_name);
408 perror (file);
b34976b6 409 return FALSE;
252b5132
RH
410 }
411 }
412
b34976b6 413 return TRUE;
252b5132
RH
414}
415\f
d132876a
NC
416/* Read the next character, return EOF if none available.
417 Assume that STREAM is positioned so that the next byte read
418 is at address ADDRESS in the file.
419
420 If STREAM is NULL, do not read from it.
421 The caller can supply a buffer of characters
422 to be processed before the data in STREAM.
423 MAGIC is the address of the buffer and
424 MAGICCOUNT is how many characters are in it. */
425
426static long
427get_char (stream, address, magiccount, magic)
428 FILE *stream;
cedd9a58 429 file_off *address;
d132876a
NC
430 int *magiccount;
431 char **magic;
432{
433 int c, i;
956cd1d6 434 long r = EOF;
d132876a
NC
435 unsigned char buf[4];
436
437 for (i = 0; i < encoding_bytes; i++)
438 {
439 if (*magiccount)
440 {
441 (*magiccount)--;
442 c = *(*magic)++;
443 }
444 else
445 {
446 if (stream == NULL)
447 return EOF;
cedd9a58
JJ
448#ifdef HAVE_GETC_UNLOCKED
449 c = getc_unlocked (stream);
450#else
d132876a 451 c = getc (stream);
cedd9a58 452#endif
d132876a
NC
453 if (c == EOF)
454 return EOF;
455 }
456
457 (*address)++;
458 buf[i] = c;
459 }
460
461 switch (encoding)
462 {
463 case 's':
464 r = buf[0];
465 break;
466 case 'b':
467 r = (buf[0] << 8) | buf[1];
468 break;
469 case 'l':
470 r = buf[0] | (buf[1] << 8);
471 break;
472 case 'B':
473 r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
474 ((long) buf[2] << 8) | buf[3];
475 break;
476 case 'L':
477 r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
478 ((long) buf[3] << 24);
479 break;
480 }
481
482 if (r == EOF)
483 return 0;
484
485 return r;
486}
487\f
252b5132
RH
488/* Find the strings in file FILENAME, read from STREAM.
489 Assume that STREAM is positioned so that the next byte read
490 is at address ADDRESS in the file.
491 Stop reading at address STOP_POINT in the file, if nonzero.
492
493 If STREAM is NULL, do not read from it.
494 The caller can supply a buffer of characters
495 to be processed before the data in STREAM.
496 MAGIC is the address of the buffer and
497 MAGICCOUNT is how many characters are in it.
498 Those characters come at address ADDRESS and the data in STREAM follow. */
499
500static void
501print_strings (filename, stream, address, stop_point, magiccount, magic)
502 const char *filename;
503 FILE *stream;
cedd9a58 504 file_off address;
252b5132
RH
505 int stop_point;
506 int magiccount;
507 char *magic;
508{
d132876a 509 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
252b5132
RH
510
511 while (1)
512 {
cedd9a58 513 file_off start;
252b5132 514 int i;
d132876a 515 long c;
252b5132
RH
516
517 /* See if the next `string_min' chars are all graphic chars. */
518 tryline:
519 if (stop_point && address >= stop_point)
520 break;
521 start = address;
522 for (i = 0; i < string_min; i++)
523 {
d132876a
NC
524 c = get_char (stream, &address, &magiccount, &magic);
525 if (c == EOF)
526 return;
527 if (c > 255 || c < 0 || !isgraphic (c))
252b5132
RH
528 /* Found a non-graphic. Try again starting with next char. */
529 goto tryline;
530 buf[i] = c;
531 }
532
533 /* We found a run of `string_min' graphic characters. Print up
534 to the next non-graphic character. */
535
536 if (print_filenames)
537 printf ("%s: ", filename);
538 if (print_addresses)
539 switch (address_radix)
540 {
541 case 8:
cedd9a58
JJ
542#if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
543 if (sizeof (start) > sizeof (long))
544 printf ("%7Lo ", (unsigned long long) start);
545 else
546#else
547# if !BFD_HOST_64BIT_LONG
548 if (start != (unsigned long) start)
549 printf ("++%7lo ", (unsigned long) start);
550 else
551# endif
552#endif
553 printf ("%7lo ", (unsigned long) start);
252b5132
RH
554 break;
555
556 case 10:
cedd9a58
JJ
557#if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
558 if (sizeof (start) > sizeof (long))
559 printf ("%7Ld ", (unsigned long long) start);
560 else
561#else
562# if !BFD_HOST_64BIT_LONG
563 if (start != (unsigned long) start)
564 printf ("++%7ld ", (unsigned long) start);
565 else
566# endif
567#endif
568 printf ("%7ld ", (long) start);
252b5132
RH
569 break;
570
571 case 16:
cedd9a58
JJ
572#if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
573 if (sizeof (start) > sizeof (long))
574 printf ("%7Lx ", (unsigned long long) start);
575 else
576#else
577# if !BFD_HOST_64BIT_LONG
578 if (start != (unsigned long) start)
579 printf ("%lx%8.8lx ", start >> 32, start & 0xffffffff);
580 else
581# endif
582#endif
583 printf ("%7lx ", (unsigned long) start);
252b5132
RH
584 break;
585 }
586
587 buf[i] = '\0';
588 fputs (buf, stdout);
589
590 while (1)
591 {
d132876a
NC
592 c = get_char (stream, &address, &magiccount, &magic);
593 if (c == EOF)
594 break;
595 if (c > 255 || c < 0 || !isgraphic (c))
252b5132
RH
596 break;
597 putchar (c);
598 }
599
600 putchar ('\n');
601 }
602}
603\f
604/* Parse string S as an integer, using decimal radix by default,
605 but allowing octal and hex numbers as in C. */
606
607static int
608integer_arg (s)
609 char *s;
610{
611 int value;
612 int radix = 10;
613 char *p = s;
614 int c;
615
616 if (*p != '0')
617 radix = 10;
618 else if (*++p == 'x')
619 {
620 radix = 16;
621 p++;
622 }
623 else
624 radix = 8;
625
626 value = 0;
627 while (((c = *p++) >= '0' && c <= '9')
628 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
629 {
630 value *= radix;
631 if (c >= '0' && c <= '9')
632 value += c - '0';
633 else
634 value += (c & ~40) - 'A';
635 }
636
637 if (c == 'b')
638 value *= 512;
639 else if (c == 'B')
640 value *= 1024;
641 else
642 p--;
643
644 if (*p)
645 {
37cc8ec1 646 fatal (_("invalid integer argument %s"), s);
252b5132
RH
647 }
648 return value;
649}
650
651static void
652usage (stream, status)
653 FILE *stream;
654 int status;
655{
8b53311e
NC
656 fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
657 fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
658 fprintf (stream, _(" The options are:\n\
659 -a - --all Scan the entire file, not just the data section\n\
660 -f --print-file-name Print the name of the file before each string\n\
661 -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
662 -<number> least [number] characters (default 4).\n\
663 -t --radix={o,x,d} Print the location of the string in base 8, 10 or 16\n\
664 -o An alias for --radix=o\n\
665 -T --target=<BFDNAME> Specify the binary file format\n\
666 -e --encoding={s,b,l,B,L} Select character size and endianness:\n\
667 s = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
668 -h --help Display this information\n\
669 -v --version Print the program's version number\n"));
252b5132
RH
670 list_supported_targets (program_name, stream);
671 if (status == 0)
8ad3436c 672 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
252b5132
RH
673 exit (status);
674}