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