]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - binutils/strings.c
* lib/insight-support.exp (_gdbtk_export_target_info): Add
[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
59#include "bfd.h"
60#include <stdio.h>
61#include <getopt.h>
62#include <ctype.h>
63#include <errno.h>
64#include "bucomm.h"
65#include "libiberty.h"
66
5af11cab
AM
67/* Some platforms need to put stdin into binary mode, to read
68 binary files. */
69#ifdef HAVE_SETMODE
70#ifndef O_BINARY
71#ifdef _O_BINARY
72#define O_BINARY _O_BINARY
73#define setmode _setmode
74#else
75#define O_BINARY 0
76#endif
77#endif
78#if O_BINARY
79#include <io.h>
80#define SET_BINARY(f) do { if (!isatty(f)) setmode(f,O_BINARY); } while (0)
81#endif
82#endif
83
1c529ca6
NC
84/* Not all printable characters have ASCII codes (depending upon the
85 LOCALE set) but on some older systems it is not safe to test isprint
86 without first testing isascii... */
87#if defined isascii && !defined HAVE_LOCALE_H
6b3bf560 88#define isgraphic(c) (isascii (c) && (isprint (c) || (c) == '\t'))
252b5132 89#else
6b3bf560 90#define isgraphic(c) (isprint (c) || (c) == '\t')
252b5132
RH
91#endif
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
100/* Radix for printing addresses (must be 8, 10 or 16). */
101static int address_radix;
102
103/* Minimum length of sequence of graphic chars to trigger output. */
104static int string_min;
105
106/* true means print address within file for each string. */
107static boolean print_addresses;
108
109/* true means print filename for each string. */
110static boolean print_filenames;
111
112/* true means for object files scan only the data section. */
113static boolean datasection_only;
114
115/* true if we found an initialized data section in the current file. */
116static boolean got_a_section;
117
118/* The BFD object file format. */
119static char *target;
120
d132876a
NC
121/* The character encoding format. */
122static char encoding;
123static int encoding_bytes;
124
252b5132
RH
125static struct option long_options[] =
126{
127 {"all", no_argument, NULL, 'a'},
128 {"print-file-name", no_argument, NULL, 'f'},
129 {"bytes", required_argument, NULL, 'n'},
130 {"radix", required_argument, NULL, 't'},
d132876a 131 {"encoding", required_argument, NULL, 'e'},
252b5132
RH
132 {"target", required_argument, NULL, 'T'},
133 {"help", no_argument, NULL, 'h'},
134 {"version", no_argument, NULL, 'v'},
135 {NULL, 0, NULL, 0}
136};
137
138static void strings_a_section PARAMS ((bfd *, asection *, PTR));
139static boolean strings_object_file PARAMS ((const char *));
140static boolean strings_file PARAMS ((char *file));
141static int integer_arg PARAMS ((char *s));
142static void print_strings PARAMS ((const char *filename, FILE *stream,
143 file_ptr address, int stop_point,
144 int magiccount, char *magic));
145static void usage PARAMS ((FILE *stream, int status));
146\f
147int
148main (argc, argv)
149 int argc;
150 char **argv;
151{
152 int optc;
153 int exit_status = 0;
154 boolean files_given = false;
155
156#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
1c529ca6 157 setlocale (LC_ALL, "");
252b5132
RH
158#endif
159 bindtextdomain (PACKAGE, LOCALEDIR);
160 textdomain (PACKAGE);
161
162 program_name = argv[0];
163 xmalloc_set_program_name (program_name);
164 string_min = -1;
165 print_addresses = false;
166 print_filenames = false;
167 datasection_only = true;
168 target = NULL;
d132876a 169 encoding = 's';
252b5132 170
d132876a 171 while ((optc = getopt_long (argc, argv, "afn:ot:e:v0123456789",
252b5132
RH
172 long_options, (int *) 0)) != EOF)
173 {
174 switch (optc)
175 {
176 case 'a':
177 datasection_only = false;
178 break;
179
180 case 'f':
181 print_filenames = true;
182 break;
183
184 case 'h':
185 usage (stdout, 0);
186
187 case 'n':
188 string_min = integer_arg (optarg);
189 if (string_min < 1)
190 {
37cc8ec1 191 fatal (_("invalid number %s"), optarg);
252b5132
RH
192 }
193 break;
194
195 case 'o':
196 print_addresses = true;
197 address_radix = 8;
198 break;
199
200 case 't':
201 print_addresses = true;
202 if (optarg[1] != '\0')
203 usage (stderr, 1);
204 switch (optarg[0])
205 {
206 case 'o':
207 address_radix = 8;
208 break;
209
210 case 'd':
211 address_radix = 10;
212 break;
213
214 case 'x':
215 address_radix = 16;
216 break;
217
218 default:
219 usage (stderr, 1);
220 }
221 break;
222
223 case 'T':
224 target = optarg;
225 break;
226
d132876a
NC
227 case 'e':
228 if (optarg[1] != '\0')
229 usage (stderr, 1);
230 encoding = optarg[0];
231 break;
232
252b5132
RH
233 case 'v':
234 print_version ("strings");
235 break;
236
237 case '?':
238 usage (stderr, 1);
239
240 default:
241 if (string_min < 0)
221f77a9 242 string_min = optc - '0';
252b5132
RH
243 else
244 string_min = string_min * 10 + optc - '0';
245 break;
246 }
247 }
248
249 if (string_min < 0)
250 string_min = 4;
251
d132876a
NC
252 switch (encoding)
253 {
254 case 's':
255 encoding_bytes = 1;
256 break;
257 case 'b':
258 case 'l':
259 encoding_bytes = 2;
260 break;
261 case 'B':
262 case 'L':
263 encoding_bytes = 4;
264 break;
265 default:
266 usage (stderr, 1);
267 }
268
252b5132
RH
269 bfd_init ();
270 set_default_bfd_target ();
271
272 if (optind >= argc)
273 {
274 datasection_only = false;
5af11cab
AM
275#ifdef SET_BINARY
276 SET_BINARY (fileno (stdin));
277#endif
252b5132
RH
278 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
279 files_given = true;
280 }
281 else
282 {
283 for (; optind < argc; ++optind)
284 {
285 if (strcmp (argv[optind], "-") == 0)
286 datasection_only = false;
287 else
288 {
289 files_given = true;
290 exit_status |= (strings_file (argv[optind]) == false);
291 }
292 }
293 }
294
295 if (files_given == false)
296 usage (stderr, 1);
297
298 return (exit_status);
299}
300\f
301/* Scan section SECT of the file ABFD, whose printable name is FILE.
302 If it contains initialized data,
303 set `got_a_section' and print the strings in it. */
304
305static void
306strings_a_section (abfd, sect, filearg)
307 bfd *abfd;
308 asection *sect;
309 PTR filearg;
310{
311 const char *file = (const char *) filearg;
312
313 if ((sect->flags & DATA_FLAGS) == DATA_FLAGS)
314 {
315 bfd_size_type sz = bfd_get_section_size_before_reloc (sect);
316 PTR mem = xmalloc (sz);
317 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz))
318 {
319 got_a_section = true;
320 print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
321 }
322 free (mem);
323 }
324}
325
326/* Scan all of the sections in FILE, and print the strings
327 in the initialized data section(s).
328
329 Return true if successful,
330 false if not (such as if FILE is not an object file). */
331
332static boolean
333strings_object_file (file)
334 const char *file;
335{
336 bfd *abfd = bfd_openr (file, target);
337
338 if (abfd == NULL)
339 {
340 /* Treat the file as a non-object file. */
341 return false;
342 }
343
344 /* This call is mainly for its side effect of reading in the sections.
345 We follow the traditional behavior of `strings' in that we don't
346 complain if we don't recognize a file to be an object file. */
347 if (bfd_check_format (abfd, bfd_object) == false)
348 {
349 bfd_close (abfd);
350 return false;
351 }
352
353 got_a_section = false;
354 bfd_map_over_sections (abfd, strings_a_section, (PTR) file);
355
356 if (!bfd_close (abfd))
357 {
358 bfd_nonfatal (file);
359 return false;
360 }
361
362 return got_a_section;
363}
364
365/* Print the strings in FILE. Return true if ok, false if an error occurs. */
366
367static boolean
368strings_file (file)
369 char *file;
370{
371 /* If we weren't told to scan the whole file,
372 try to open it as an object file and only look at
373 initialized data sections. If that fails, fall back to the
374 whole file. */
375 if (!datasection_only || !strings_object_file (file))
376 {
377 FILE *stream;
378
379 stream = fopen (file, "rb");
380 /* Not all systems permit "rb", so try "r" if it failed. */
381 if (stream == NULL)
382 stream = fopen (file, "r");
383 if (stream == NULL)
384 {
385 fprintf (stderr, "%s: ", program_name);
386 perror (file);
387 return false;
388 }
389
390 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
391
392 if (fclose (stream) == EOF)
393 {
394 fprintf (stderr, "%s: ", program_name);
395 perror (file);
396 return false;
397 }
398 }
399
400 return true;
401}
402\f
d132876a
NC
403/* Read the next character, return EOF if none available.
404 Assume that STREAM is positioned so that the next byte read
405 is at address ADDRESS in the file.
406
407 If STREAM is NULL, do not read from it.
408 The caller can supply a buffer of characters
409 to be processed before the data in STREAM.
410 MAGIC is the address of the buffer and
411 MAGICCOUNT is how many characters are in it. */
412
413static long
414get_char (stream, address, magiccount, magic)
415 FILE *stream;
416 file_ptr *address;
417 int *magiccount;
418 char **magic;
419{
420 int c, i;
421 long r;
422 unsigned char buf[4];
423
424 for (i = 0; i < encoding_bytes; i++)
425 {
426 if (*magiccount)
427 {
428 (*magiccount)--;
429 c = *(*magic)++;
430 }
431 else
432 {
433 if (stream == NULL)
434 return EOF;
435 c = getc (stream);
436 if (c == EOF)
437 return EOF;
438 }
439
440 (*address)++;
441 buf[i] = c;
442 }
443
444 switch (encoding)
445 {
446 case 's':
447 r = buf[0];
448 break;
449 case 'b':
450 r = (buf[0] << 8) | buf[1];
451 break;
452 case 'l':
453 r = buf[0] | (buf[1] << 8);
454 break;
455 case 'B':
456 r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
457 ((long) buf[2] << 8) | buf[3];
458 break;
459 case 'L':
460 r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
461 ((long) buf[3] << 24);
462 break;
463 }
464
465 if (r == EOF)
466 return 0;
467
468 return r;
469}
470\f
252b5132
RH
471/* Find the strings in file FILENAME, read from STREAM.
472 Assume that STREAM is positioned so that the next byte read
473 is at address ADDRESS in the file.
474 Stop reading at address STOP_POINT in the file, if nonzero.
475
476 If STREAM is NULL, do not read from it.
477 The caller can supply a buffer of characters
478 to be processed before the data in STREAM.
479 MAGIC is the address of the buffer and
480 MAGICCOUNT is how many characters are in it.
481 Those characters come at address ADDRESS and the data in STREAM follow. */
482
483static void
484print_strings (filename, stream, address, stop_point, magiccount, magic)
485 const char *filename;
486 FILE *stream;
487 file_ptr address;
488 int stop_point;
489 int magiccount;
490 char *magic;
491{
d132876a 492 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
252b5132
RH
493
494 while (1)
495 {
496 file_ptr start;
497 int i;
d132876a 498 long c;
252b5132
RH
499
500 /* See if the next `string_min' chars are all graphic chars. */
501 tryline:
502 if (stop_point && address >= stop_point)
503 break;
504 start = address;
505 for (i = 0; i < string_min; i++)
506 {
d132876a
NC
507 c = get_char (stream, &address, &magiccount, &magic);
508 if (c == EOF)
509 return;
510 if (c > 255 || c < 0 || !isgraphic (c))
252b5132
RH
511 /* Found a non-graphic. Try again starting with next char. */
512 goto tryline;
513 buf[i] = c;
514 }
515
516 /* We found a run of `string_min' graphic characters. Print up
517 to the next non-graphic character. */
518
519 if (print_filenames)
520 printf ("%s: ", filename);
521 if (print_addresses)
522 switch (address_radix)
523 {
524 case 8:
525 printf ("%7lo ", (unsigned long) start);
526 break;
527
528 case 10:
529 printf ("%7ld ", (long) start);
530 break;
531
532 case 16:
533 printf ("%7lx ", (unsigned long) start);
534 break;
535 }
536
537 buf[i] = '\0';
538 fputs (buf, stdout);
539
540 while (1)
541 {
d132876a
NC
542 c = get_char (stream, &address, &magiccount, &magic);
543 if (c == EOF)
544 break;
545 if (c > 255 || c < 0 || !isgraphic (c))
252b5132
RH
546 break;
547 putchar (c);
548 }
549
550 putchar ('\n');
551 }
552}
553\f
554/* Parse string S as an integer, using decimal radix by default,
555 but allowing octal and hex numbers as in C. */
556
557static int
558integer_arg (s)
559 char *s;
560{
561 int value;
562 int radix = 10;
563 char *p = s;
564 int c;
565
566 if (*p != '0')
567 radix = 10;
568 else if (*++p == 'x')
569 {
570 radix = 16;
571 p++;
572 }
573 else
574 radix = 8;
575
576 value = 0;
577 while (((c = *p++) >= '0' && c <= '9')
578 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
579 {
580 value *= radix;
581 if (c >= '0' && c <= '9')
582 value += c - '0';
583 else
584 value += (c & ~40) - 'A';
585 }
586
587 if (c == 'b')
588 value *= 512;
589 else if (c == 'B')
590 value *= 1024;
591 else
592 p--;
593
594 if (*p)
595 {
37cc8ec1 596 fatal (_("invalid integer argument %s"), s);
252b5132
RH
597 }
598 return value;
599}
600
601static void
602usage (stream, status)
603 FILE *stream;
604 int status;
605{
606 fprintf (stream, _("\
d132876a
NC
607Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-e {s,b,l,B,L}]\n\
608 [-] [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
609 [--target=bfdname] [--encoding {s,b,l,B,L}] [--help] [--version] file...\n"),
252b5132
RH
610 program_name);
611 list_supported_targets (program_name, stream);
612 if (status == 0)
8ad3436c 613 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
252b5132
RH
614 exit (status);
615}