1 /* strings -- print the strings of printable characters in files
2 Copyright (C) 1993, 94 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Usage: strings [options] file...
23 - Do not scan only the initialized data section of object files.
26 -f Print the name of the file before each string.
30 -min-len Print graphic char sequences, MIN-LEN or more bytes long,
31 that are followed by a NUL or a newline. Default is 4.
34 -t {o,x,d} Print the offset within the file before each string,
37 -o Like -to. (Some other implementations have -o like -to,
38 others like -td. We chose one arbitrarily.)
41 Specify a non-default object file format.
44 -h Print the usage message on the standard output.
47 -v Print the program version number.
49 Written by Richard Stallman <rms@gnu.ai.mit.edu>
50 and David MacKenzie <djm@gnu.ai.mit.edu>. */
60 #define isgraphic(c) (isascii (c) && isprint (c))
62 #define isgraphic(c) (isprint (c))
69 /* The BFD section flags that identify an initialized data section. */
70 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS)
72 /* Radix for printing addresses (must be 8, 10 or 16). */
73 static int address_radix;
75 /* Minimum length of sequence of graphic chars to trigger output. */
76 static int string_min;
78 /* true means print address within file for each string. */
79 static boolean print_addresses;
81 /* true means print filename for each string. */
82 static boolean print_filenames;
84 /* true means for object files scan only the data section. */
85 static boolean datasection_only;
87 /* true if we found an initialized data section in the current file. */
88 static boolean got_a_section;
90 /* The BFD object file format. */
93 extern char *program_version;
95 static struct option long_options[] =
97 {"all", no_argument, NULL, 'a'},
98 {"print-file-name", no_argument, NULL, 'f'},
99 {"bytes", required_argument, NULL, 'n'},
100 {"radix", required_argument, NULL, 't'},
101 {"target", required_argument, NULL, 'T'},
102 {"help", no_argument, NULL, 'h'},
103 {"version", no_argument, NULL, 'v'},
107 static boolean strings_file PARAMS ((char *file));
108 static int integer_arg PARAMS ((char *s));
109 static void print_strings PARAMS ((char *filename, FILE *stream,
110 file_ptr address, int stop_point,
111 int magiccount, char *magic));
112 static void usage PARAMS ((FILE *stream, int status));
121 boolean files_given = false;
123 program_name = argv[0];
125 print_addresses = false;
126 print_filenames = false;
127 datasection_only = true;
130 while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789",
131 long_options, (int *) 0)) != EOF)
136 datasection_only = false;
140 print_filenames = true;
147 string_min = integer_arg (optarg);
150 fprintf (stderr, "%s: invalid number %s\n",
151 program_name, optarg);
157 print_addresses = true;
162 print_addresses = true;
163 if (optarg[1] != '\0')
189 printf ("GNU %s version %s\n", program_name, program_version);
199 string_min = string_min * 10 + optc - '0';
209 for (; optind < argc; ++optind)
211 if (!strcmp (argv[optind], "-"))
212 datasection_only = false;
216 exit_status |= (strings_file (argv[optind]) == false);
220 if (files_given == false)
226 /* Scan section SECT of the file ABFD, whose printable name is FILE.
227 If it contains initialized data,
228 set `got_a_section' and print the strings in it. */
231 strings_a_section (abfd, sect, file)
236 if ((sect->flags & DATA_FLAGS) == DATA_FLAGS)
238 bfd_size_type sz = bfd_get_section_size_before_reloc (sect);
239 PTR mem = xmalloc (sz);
240 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz))
242 got_a_section = true;
243 print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
249 /* Scan all of the sections in FILE, and print the strings
250 in the initialized data section(s).
252 Return true if successful,
253 false if not (such as if FILE is not an object file). */
256 strings_object_file (file)
259 bfd *abfd = bfd_openr (file, target);
263 /* Treat the file as a non-object file. */
267 /* This call is mainly for its side effect of reading in the sections.
268 We follow the traditional behavior of `strings' in that we don't
269 complain if we don't recognize a file to be an object file. */
270 if (bfd_check_format (abfd, bfd_object) == false)
276 got_a_section = false;
277 bfd_map_over_sections (abfd, strings_a_section, file);
279 if (!bfd_close (abfd))
285 return got_a_section;
288 /* Print the strings in FILE. Return true if ok, false if an error occurs. */
294 /* If we weren't told to scan the whole file,
295 try to open it as an object file and only look at
296 initialized data sections. If that fails, fall back to the
298 if (!datasection_only || !strings_object_file (file))
302 stream = fopen (file, "r");
305 fprintf (stderr, "%s: ", program_name);
310 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
312 if (fclose (stream) == EOF)
314 fprintf (stderr, "%s: ", program_name);
323 /* Find the strings in file FILENAME, read from STREAM.
324 Assume that STREAM is positioned so that the next byte read
325 is at address ADDRESS in the file.
326 Stop reading at address STOP_POINT in the file, if nonzero.
328 If STREAM is NULL, do not read from it.
329 The caller can supply a buffer of characters
330 to be processed before the data in STREAM.
331 MAGIC is the address of the buffer and
332 MAGICCOUNT is how many characters are in it.
333 Those characters come at address ADDRESS and the data in STREAM follow. */
336 print_strings (filename, stream, address, stop_point, magiccount, magic)
345 char *buf = (char *) xmalloc (bufsize);
352 /* See if the next `string_min' chars are all graphic chars. */
354 if (stop_point && address >= stop_point)
356 for (i = 0; i < string_min; i++)
373 /* Found a non-graphic. Try again starting with next char. */
378 /* We found a run of `string_min' graphic characters.
379 Now see if it is terminated with a NUL byte or a newline. */
385 buf = (char *) xrealloc (buf, bufsize);
401 if (c == '\0' || c == '\n')
402 break; /* It is; print this string. */
404 goto tryline; /* It isn't; give up on this string. */
405 buf[i++] = c; /* The string continues; store it all. */
408 /* If we get here, the string is all graphics and properly terminated,
409 so print it. It is all in `buf' and `i' is its length. */
412 printf ("%s: ", filename);
414 switch (address_radix)
417 printf ("%7lo ", (unsigned long) (address - i - 1));
421 printf ("%7ld ", (long) (address - i - 1));
425 printf ("%7lx ", (unsigned long) (address - i - 1));
429 for (i = 0; (c = buf[i]) != '\0'; i++)
454 /* Parse string S as an integer, using decimal radix by default,
455 but allowing octal and hex numbers as in C. */
468 else if (*++p == 'x')
477 while (((c = *p++) >= '0' && c <= '9')
478 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
481 if (c >= '0' && c <= '9')
484 value += (c & ~40) - 'A';
496 fprintf (stderr, "%s: invalid integer argument %s\n", program_name, s);
503 usage (stream, status)
508 Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\
509 [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
510 [--target=bfdname] [--help] [--version] file...\n",