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