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