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