1 /* strings -- print the strings of printable characters in files
2 Copyright (C) 1993, 94, 95, 96, 97, 1998 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., 59 Temple Place - Suite 330, Boston, MA
19 /* Usage: strings [options] file...
24 - Do not scan only the initialized data section of object files.
27 -f Print the name of the file before each string.
31 -min-len Print graphic char sequences, MIN-LEN or more bytes long,
32 that are followed by a NUL or a newline. Default is 4.
35 -t {o,x,d} Print the offset within the file before each string,
38 -o Like -to. (Some other implementations have -o like -to,
39 others like -td. We chose one arbitrarily.)
42 Specify a non-default object file format.
45 -h Print the usage message on the standard output.
48 -v Print the program version number.
50 Written by Richard Stallman <rms@gnu.ai.mit.edu>
51 and David MacKenzie <djm@gnu.ai.mit.edu>. */
59 #include "libiberty.h"
62 #define isgraphic(c) (isascii (c) && isprint (c))
64 #define isgraphic(c) (isprint (c))
71 /* The BFD section flags that identify an initialized data section. */
72 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
74 /* Radix for printing addresses (must be 8, 10 or 16). */
75 static int address_radix
;
77 /* Minimum length of sequence of graphic chars to trigger output. */
78 static int string_min
;
80 /* true means print address within file for each string. */
81 static boolean print_addresses
;
83 /* true means print filename for each string. */
84 static boolean print_filenames
;
86 /* true means for object files scan only the data section. */
87 static boolean datasection_only
;
89 /* true if we found an initialized data section in the current file. */
90 static boolean got_a_section
;
92 /* The BFD object file format. */
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 void strings_a_section
PARAMS ((bfd
*, asection
*, PTR
));
108 static boolean strings_object_file
PARAMS ((const char *));
109 static boolean strings_file
PARAMS ((char *file
));
110 static int integer_arg
PARAMS ((char *s
));
111 static void print_strings
PARAMS ((const char *filename
, FILE *stream
,
112 file_ptr address
, int stop_point
,
113 int magiccount
, char *magic
));
114 static void usage
PARAMS ((FILE *stream
, int status
));
123 boolean files_given
= false;
125 setlocale (LC_MESSAGES
, "");
126 bindtextdomain (PACKAGE
, LOCALEDIR
);
127 textdomain (PACKAGE
);
129 program_name
= argv
[0];
130 xmalloc_set_program_name (program_name
);
132 print_addresses
= false;
133 print_filenames
= false;
134 datasection_only
= true;
137 while ((optc
= getopt_long (argc
, argv
, "afn:ot:v0123456789",
138 long_options
, (int *) 0)) != EOF
)
143 datasection_only
= false;
147 print_filenames
= true;
154 string_min
= integer_arg (optarg
);
157 fprintf (stderr
, _("%s: invalid number %s\n"),
158 program_name
, optarg
);
164 print_addresses
= true;
169 print_addresses
= true;
170 if (optarg
[1] != '\0')
196 print_version ("strings");
206 string_min
= string_min
* 10 + optc
- '0';
215 set_default_bfd_target ();
219 datasection_only
= false;
220 print_strings ("{standard input}", stdin
, 0, 0, 0, (char *) NULL
);
225 for (; optind
< argc
; ++optind
)
227 if (strcmp (argv
[optind
], "-") == 0)
228 datasection_only
= false;
232 exit_status
|= (strings_file (argv
[optind
]) == false);
237 if (files_given
== false)
240 return (exit_status
);
243 /* Scan section SECT of the file ABFD, whose printable name is FILE.
244 If it contains initialized data,
245 set `got_a_section' and print the strings in it. */
248 strings_a_section (abfd
, sect
, filearg
)
253 const char *file
= (const char *) filearg
;
255 if ((sect
->flags
& DATA_FLAGS
) == DATA_FLAGS
)
257 bfd_size_type sz
= bfd_get_section_size_before_reloc (sect
);
258 PTR mem
= xmalloc (sz
);
259 if (bfd_get_section_contents (abfd
, sect
, mem
, (file_ptr
) 0, sz
))
261 got_a_section
= true;
262 print_strings (file
, (FILE *) NULL
, sect
->filepos
, 0, sz
, mem
);
268 /* Scan all of the sections in FILE, and print the strings
269 in the initialized data section(s).
271 Return true if successful,
272 false if not (such as if FILE is not an object file). */
275 strings_object_file (file
)
278 bfd
*abfd
= bfd_openr (file
, target
);
282 /* Treat the file as a non-object file. */
286 /* This call is mainly for its side effect of reading in the sections.
287 We follow the traditional behavior of `strings' in that we don't
288 complain if we don't recognize a file to be an object file. */
289 if (bfd_check_format (abfd
, bfd_object
) == false)
295 got_a_section
= false;
296 bfd_map_over_sections (abfd
, strings_a_section
, (PTR
) file
);
298 if (!bfd_close (abfd
))
304 return got_a_section
;
307 /* Print the strings in FILE. Return true if ok, false if an error occurs. */
313 /* If we weren't told to scan the whole file,
314 try to open it as an object file and only look at
315 initialized data sections. If that fails, fall back to the
317 if (!datasection_only
|| !strings_object_file (file
))
321 stream
= fopen (file
, "rb");
322 /* Not all systems permit "rb", so try "r" if it failed. */
324 stream
= fopen (file
, "r");
327 fprintf (stderr
, "%s: ", program_name
);
332 print_strings (file
, stream
, (file_ptr
) 0, 0, 0, (char *) 0);
334 if (fclose (stream
) == EOF
)
336 fprintf (stderr
, "%s: ", program_name
);
345 /* Find the strings in file FILENAME, read from STREAM.
346 Assume that STREAM is positioned so that the next byte read
347 is at address ADDRESS in the file.
348 Stop reading at address STOP_POINT in the file, if nonzero.
350 If STREAM is NULL, do not read from it.
351 The caller can supply a buffer of characters
352 to be processed before the data in STREAM.
353 MAGIC is the address of the buffer and
354 MAGICCOUNT is how many characters are in it.
355 Those characters come at address ADDRESS and the data in STREAM follow. */
358 print_strings (filename
, stream
, address
, stop_point
, magiccount
, magic
)
359 const char *filename
;
366 char *buf
= (char *) xmalloc (string_min
+ 1);
374 /* See if the next `string_min' chars are all graphic chars. */
376 if (stop_point
&& address
>= stop_point
)
379 for (i
= 0; i
< string_min
; i
++)
396 /* Found a non-graphic. Try again starting with next char. */
401 /* We found a run of `string_min' graphic characters. Print up
402 to the next non-graphic character. */
405 printf ("%s: ", filename
);
407 switch (address_radix
)
410 printf ("%7lo ", (unsigned long) start
);
414 printf ("%7ld ", (long) start
);
418 printf ("%7lx ", (unsigned long) start
);
450 /* Parse string S as an integer, using decimal radix by default,
451 but allowing octal and hex numbers as in C. */
464 else if (*++p
== 'x')
473 while (((c
= *p
++) >= '0' && c
<= '9')
474 || (radix
== 16 && (c
& ~40) >= 'A' && (c
& ~40) <= 'Z'))
477 if (c
>= '0' && c
<= '9')
480 value
+= (c
& ~40) - 'A';
492 fprintf (stderr
, _("%s: invalid integer argument %s\n"), program_name
, s
);
499 usage (stream
, status
)
503 fprintf (stream
, _("\
504 Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\
505 [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
506 [--target=bfdname] [--help] [--version] file...\n"),
508 list_supported_targets (program_name
, stream
);
510 fprintf (stream
, _("Report bugs to bug-gnu-utils@gnu.org\n"));