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