1*a9fa9459Szrj /* strings -- print the strings of printable characters in files
2*a9fa9459Szrj Copyright (C) 1993-2016 Free Software Foundation, Inc.
3*a9fa9459Szrj
4*a9fa9459Szrj This program is free software; you can redistribute it and/or modify
5*a9fa9459Szrj it under the terms of the GNU General Public License as published by
6*a9fa9459Szrj the Free Software Foundation; either version 3, or (at your option)
7*a9fa9459Szrj any later version.
8*a9fa9459Szrj
9*a9fa9459Szrj This program is distributed in the hope that it will be useful,
10*a9fa9459Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
11*a9fa9459Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*a9fa9459Szrj GNU General Public License for more details.
13*a9fa9459Szrj
14*a9fa9459Szrj You should have received a copy of the GNU General Public License
15*a9fa9459Szrj along with this program; if not, write to the Free Software
16*a9fa9459Szrj Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
17*a9fa9459Szrj 02110-1301, USA. */
18*a9fa9459Szrj
19*a9fa9459Szrj /* Usage: strings [options] file...
20*a9fa9459Szrj
21*a9fa9459Szrj Options:
22*a9fa9459Szrj --all
23*a9fa9459Szrj -a
24*a9fa9459Szrj - Scan each file in its entirety.
25*a9fa9459Szrj
26*a9fa9459Szrj --data
27*a9fa9459Szrj -d Scan only the initialized data section(s) of object files.
28*a9fa9459Szrj
29*a9fa9459Szrj --print-file-name
30*a9fa9459Szrj -f Print the name of the file before each string.
31*a9fa9459Szrj
32*a9fa9459Szrj --bytes=min-len
33*a9fa9459Szrj -n min-len
34*a9fa9459Szrj -min-len Print graphic char sequences, MIN-LEN or more bytes long,
35*a9fa9459Szrj that are followed by a NUL or a newline. Default is 4.
36*a9fa9459Szrj
37*a9fa9459Szrj --radix={o,x,d}
38*a9fa9459Szrj -t {o,x,d} Print the offset within the file before each string,
39*a9fa9459Szrj in octal/hex/decimal.
40*a9fa9459Szrj
41*a9fa9459Szrj --include-all-whitespace
42*a9fa9459Szrj -w By default tab and space are the only whitepace included in graphic
43*a9fa9459Szrj char sequences. This option considers all of isspace() valid.
44*a9fa9459Szrj
45*a9fa9459Szrj -o Like -to. (Some other implementations have -o like -to,
46*a9fa9459Szrj others like -td. We chose one arbitrarily.)
47*a9fa9459Szrj
48*a9fa9459Szrj --encoding={s,S,b,l,B,L}
49*a9fa9459Szrj -e {s,S,b,l,B,L}
50*a9fa9459Szrj Select character encoding: 7-bit-character, 8-bit-character,
51*a9fa9459Szrj bigendian 16-bit, littleendian 16-bit, bigendian 32-bit,
52*a9fa9459Szrj littleendian 32-bit.
53*a9fa9459Szrj
54*a9fa9459Szrj --target=BFDNAME
55*a9fa9459Szrj -T {bfdname}
56*a9fa9459Szrj Specify a non-default object file format.
57*a9fa9459Szrj
58*a9fa9459Szrj --output-separator=sep_string
59*a9fa9459Szrj -s sep_string String used to separate parsed strings in output.
60*a9fa9459Szrj Default is newline.
61*a9fa9459Szrj
62*a9fa9459Szrj --help
63*a9fa9459Szrj -h Print the usage message on the standard output.
64*a9fa9459Szrj
65*a9fa9459Szrj --version
66*a9fa9459Szrj -V
67*a9fa9459Szrj -v Print the program version number.
68*a9fa9459Szrj
69*a9fa9459Szrj Written by Richard Stallman <rms@gnu.ai.mit.edu>
70*a9fa9459Szrj and David MacKenzie <djm@gnu.ai.mit.edu>. */
71*a9fa9459Szrj
72*a9fa9459Szrj #include "sysdep.h"
73*a9fa9459Szrj #include "bfd.h"
74*a9fa9459Szrj #include "getopt.h"
75*a9fa9459Szrj #include "libiberty.h"
76*a9fa9459Szrj #include "safe-ctype.h"
77*a9fa9459Szrj #include "bucomm.h"
78*a9fa9459Szrj
79*a9fa9459Szrj #define STRING_ISGRAPHIC(c) \
80*a9fa9459Szrj ( (c) >= 0 \
81*a9fa9459Szrj && (c) <= 255 \
82*a9fa9459Szrj && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127) \
83*a9fa9459Szrj || (include_all_whitespace == TRUE && ISSPACE (c))) \
84*a9fa9459Szrj )
85*a9fa9459Szrj
86*a9fa9459Szrj #ifndef errno
87*a9fa9459Szrj extern int errno;
88*a9fa9459Szrj #endif
89*a9fa9459Szrj
90*a9fa9459Szrj /* The BFD section flags that identify an initialized data section. */
91*a9fa9459Szrj #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
92*a9fa9459Szrj
93*a9fa9459Szrj /* Radix for printing addresses (must be 8, 10 or 16). */
94*a9fa9459Szrj static int address_radix;
95*a9fa9459Szrj
96*a9fa9459Szrj /* Minimum length of sequence of graphic chars to trigger output. */
97*a9fa9459Szrj static int string_min;
98*a9fa9459Szrj
99*a9fa9459Szrj /* Whether or not we include all whitespace as a graphic char. */
100*a9fa9459Szrj static bfd_boolean include_all_whitespace;
101*a9fa9459Szrj
102*a9fa9459Szrj /* TRUE means print address within file for each string. */
103*a9fa9459Szrj static bfd_boolean print_addresses;
104*a9fa9459Szrj
105*a9fa9459Szrj /* TRUE means print filename for each string. */
106*a9fa9459Szrj static bfd_boolean print_filenames;
107*a9fa9459Szrj
108*a9fa9459Szrj /* TRUE means for object files scan only the data section. */
109*a9fa9459Szrj static bfd_boolean datasection_only;
110*a9fa9459Szrj
111*a9fa9459Szrj /* TRUE if we found an initialized data section in the current file. */
112*a9fa9459Szrj static bfd_boolean got_a_section;
113*a9fa9459Szrj
114*a9fa9459Szrj /* The BFD object file format. */
115*a9fa9459Szrj static char *target;
116*a9fa9459Szrj
117*a9fa9459Szrj /* The character encoding format. */
118*a9fa9459Szrj static char encoding;
119*a9fa9459Szrj static int encoding_bytes;
120*a9fa9459Szrj
121*a9fa9459Szrj /* Output string used to separate parsed strings */
122*a9fa9459Szrj static char *output_separator;
123*a9fa9459Szrj
124*a9fa9459Szrj static struct option long_options[] =
125*a9fa9459Szrj {
126*a9fa9459Szrj {"all", no_argument, NULL, 'a'},
127*a9fa9459Szrj {"data", no_argument, NULL, 'd'},
128*a9fa9459Szrj {"print-file-name", no_argument, NULL, 'f'},
129*a9fa9459Szrj {"bytes", required_argument, NULL, 'n'},
130*a9fa9459Szrj {"radix", required_argument, NULL, 't'},
131*a9fa9459Szrj {"include-all-whitespace", required_argument, NULL, 'w'},
132*a9fa9459Szrj {"encoding", required_argument, NULL, 'e'},
133*a9fa9459Szrj {"target", required_argument, NULL, 'T'},
134*a9fa9459Szrj {"output-separator", required_argument, NULL, 's'},
135*a9fa9459Szrj {"help", no_argument, NULL, 'h'},
136*a9fa9459Szrj {"version", no_argument, NULL, 'v'},
137*a9fa9459Szrj {NULL, 0, NULL, 0}
138*a9fa9459Szrj };
139*a9fa9459Szrj
140*a9fa9459Szrj /* Records the size of a named file so that we
141*a9fa9459Szrj do not repeatedly run bfd_stat() on it. */
142*a9fa9459Szrj
143*a9fa9459Szrj typedef struct
144*a9fa9459Szrj {
145*a9fa9459Szrj const char * filename;
146*a9fa9459Szrj bfd_size_type filesize;
147*a9fa9459Szrj } filename_and_size_t;
148*a9fa9459Szrj
149*a9fa9459Szrj static void strings_a_section (bfd *, asection *, void *);
150*a9fa9459Szrj static bfd_boolean strings_object_file (const char *);
151*a9fa9459Szrj static bfd_boolean strings_file (char *);
152*a9fa9459Szrj static void print_strings (const char *, FILE *, file_ptr, int, int, char *);
153*a9fa9459Szrj static void usage (FILE *, int);
154*a9fa9459Szrj static long get_char (FILE *, file_ptr *, int *, char **);
155*a9fa9459Szrj
156*a9fa9459Szrj int main (int, char **);
157*a9fa9459Szrj
158*a9fa9459Szrj int
main(int argc,char ** argv)159*a9fa9459Szrj main (int argc, char **argv)
160*a9fa9459Szrj {
161*a9fa9459Szrj int optc;
162*a9fa9459Szrj int exit_status = 0;
163*a9fa9459Szrj bfd_boolean files_given = FALSE;
164*a9fa9459Szrj char *s;
165*a9fa9459Szrj int numeric_opt = 0;
166*a9fa9459Szrj
167*a9fa9459Szrj #if defined (HAVE_SETLOCALE)
168*a9fa9459Szrj setlocale (LC_ALL, "");
169*a9fa9459Szrj #endif
170*a9fa9459Szrj bindtextdomain (PACKAGE, LOCALEDIR);
171*a9fa9459Szrj textdomain (PACKAGE);
172*a9fa9459Szrj
173*a9fa9459Szrj program_name = argv[0];
174*a9fa9459Szrj xmalloc_set_program_name (program_name);
175*a9fa9459Szrj bfd_set_error_program_name (program_name);
176*a9fa9459Szrj
177*a9fa9459Szrj expandargv (&argc, &argv);
178*a9fa9459Szrj
179*a9fa9459Szrj string_min = 4;
180*a9fa9459Szrj include_all_whitespace = FALSE;
181*a9fa9459Szrj print_addresses = FALSE;
182*a9fa9459Szrj print_filenames = FALSE;
183*a9fa9459Szrj if (DEFAULT_STRINGS_ALL)
184*a9fa9459Szrj datasection_only = FALSE;
185*a9fa9459Szrj else
186*a9fa9459Szrj datasection_only = TRUE;
187*a9fa9459Szrj target = NULL;
188*a9fa9459Szrj encoding = 's';
189*a9fa9459Szrj output_separator = NULL;
190*a9fa9459Szrj
191*a9fa9459Szrj while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:Vv0123456789",
192*a9fa9459Szrj long_options, (int *) 0)) != EOF)
193*a9fa9459Szrj {
194*a9fa9459Szrj switch (optc)
195*a9fa9459Szrj {
196*a9fa9459Szrj case 'a':
197*a9fa9459Szrj datasection_only = FALSE;
198*a9fa9459Szrj break;
199*a9fa9459Szrj
200*a9fa9459Szrj case 'd':
201*a9fa9459Szrj datasection_only = TRUE;
202*a9fa9459Szrj break;
203*a9fa9459Szrj
204*a9fa9459Szrj case 'f':
205*a9fa9459Szrj print_filenames = TRUE;
206*a9fa9459Szrj break;
207*a9fa9459Szrj
208*a9fa9459Szrj case 'H':
209*a9fa9459Szrj case 'h':
210*a9fa9459Szrj usage (stdout, 0);
211*a9fa9459Szrj
212*a9fa9459Szrj case 'n':
213*a9fa9459Szrj string_min = (int) strtoul (optarg, &s, 0);
214*a9fa9459Szrj if (s != NULL && *s != 0)
215*a9fa9459Szrj fatal (_("invalid integer argument %s"), optarg);
216*a9fa9459Szrj break;
217*a9fa9459Szrj
218*a9fa9459Szrj case 'w':
219*a9fa9459Szrj include_all_whitespace = TRUE;
220*a9fa9459Szrj break;
221*a9fa9459Szrj
222*a9fa9459Szrj case 'o':
223*a9fa9459Szrj print_addresses = TRUE;
224*a9fa9459Szrj address_radix = 8;
225*a9fa9459Szrj break;
226*a9fa9459Szrj
227*a9fa9459Szrj case 't':
228*a9fa9459Szrj print_addresses = TRUE;
229*a9fa9459Szrj if (optarg[1] != '\0')
230*a9fa9459Szrj usage (stderr, 1);
231*a9fa9459Szrj switch (optarg[0])
232*a9fa9459Szrj {
233*a9fa9459Szrj case 'o':
234*a9fa9459Szrj address_radix = 8;
235*a9fa9459Szrj break;
236*a9fa9459Szrj
237*a9fa9459Szrj case 'd':
238*a9fa9459Szrj address_radix = 10;
239*a9fa9459Szrj break;
240*a9fa9459Szrj
241*a9fa9459Szrj case 'x':
242*a9fa9459Szrj address_radix = 16;
243*a9fa9459Szrj break;
244*a9fa9459Szrj
245*a9fa9459Szrj default:
246*a9fa9459Szrj usage (stderr, 1);
247*a9fa9459Szrj }
248*a9fa9459Szrj break;
249*a9fa9459Szrj
250*a9fa9459Szrj case 'T':
251*a9fa9459Szrj target = optarg;
252*a9fa9459Szrj break;
253*a9fa9459Szrj
254*a9fa9459Szrj case 'e':
255*a9fa9459Szrj if (optarg[1] != '\0')
256*a9fa9459Szrj usage (stderr, 1);
257*a9fa9459Szrj encoding = optarg[0];
258*a9fa9459Szrj break;
259*a9fa9459Szrj
260*a9fa9459Szrj case 's':
261*a9fa9459Szrj output_separator = optarg;
262*a9fa9459Szrj break;
263*a9fa9459Szrj
264*a9fa9459Szrj case 'V':
265*a9fa9459Szrj case 'v':
266*a9fa9459Szrj print_version ("strings");
267*a9fa9459Szrj break;
268*a9fa9459Szrj
269*a9fa9459Szrj case '?':
270*a9fa9459Szrj usage (stderr, 1);
271*a9fa9459Szrj
272*a9fa9459Szrj default:
273*a9fa9459Szrj numeric_opt = optind;
274*a9fa9459Szrj break;
275*a9fa9459Szrj }
276*a9fa9459Szrj }
277*a9fa9459Szrj
278*a9fa9459Szrj if (numeric_opt != 0)
279*a9fa9459Szrj {
280*a9fa9459Szrj string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0);
281*a9fa9459Szrj if (s != NULL && *s != 0)
282*a9fa9459Szrj fatal (_("invalid integer argument %s"), argv[numeric_opt - 1] + 1);
283*a9fa9459Szrj }
284*a9fa9459Szrj if (string_min < 1)
285*a9fa9459Szrj fatal (_("invalid minimum string length %d"), string_min);
286*a9fa9459Szrj
287*a9fa9459Szrj switch (encoding)
288*a9fa9459Szrj {
289*a9fa9459Szrj case 'S':
290*a9fa9459Szrj case 's':
291*a9fa9459Szrj encoding_bytes = 1;
292*a9fa9459Szrj break;
293*a9fa9459Szrj case 'b':
294*a9fa9459Szrj case 'l':
295*a9fa9459Szrj encoding_bytes = 2;
296*a9fa9459Szrj break;
297*a9fa9459Szrj case 'B':
298*a9fa9459Szrj case 'L':
299*a9fa9459Szrj encoding_bytes = 4;
300*a9fa9459Szrj break;
301*a9fa9459Szrj default:
302*a9fa9459Szrj usage (stderr, 1);
303*a9fa9459Szrj }
304*a9fa9459Szrj
305*a9fa9459Szrj bfd_init ();
306*a9fa9459Szrj set_default_bfd_target ();
307*a9fa9459Szrj
308*a9fa9459Szrj if (optind >= argc)
309*a9fa9459Szrj {
310*a9fa9459Szrj datasection_only = FALSE;
311*a9fa9459Szrj SET_BINARY (fileno (stdin));
312*a9fa9459Szrj print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
313*a9fa9459Szrj files_given = TRUE;
314*a9fa9459Szrj }
315*a9fa9459Szrj else
316*a9fa9459Szrj {
317*a9fa9459Szrj for (; optind < argc; ++optind)
318*a9fa9459Szrj {
319*a9fa9459Szrj if (strcmp (argv[optind], "-") == 0)
320*a9fa9459Szrj datasection_only = FALSE;
321*a9fa9459Szrj else
322*a9fa9459Szrj {
323*a9fa9459Szrj files_given = TRUE;
324*a9fa9459Szrj exit_status |= strings_file (argv[optind]) == FALSE;
325*a9fa9459Szrj }
326*a9fa9459Szrj }
327*a9fa9459Szrj }
328*a9fa9459Szrj
329*a9fa9459Szrj if (!files_given)
330*a9fa9459Szrj usage (stderr, 1);
331*a9fa9459Szrj
332*a9fa9459Szrj return (exit_status);
333*a9fa9459Szrj }
334*a9fa9459Szrj
335*a9fa9459Szrj /* Scan section SECT of the file ABFD, whose printable name is in
336*a9fa9459Szrj ARG->filename and whose size might be in ARG->filesize. If it
337*a9fa9459Szrj contains initialized data set `got_a_section' and print the
338*a9fa9459Szrj strings in it.
339*a9fa9459Szrj
340*a9fa9459Szrj FIXME: We ought to be able to return error codes/messages for
341*a9fa9459Szrj certain conditions. */
342*a9fa9459Szrj
343*a9fa9459Szrj static void
strings_a_section(bfd * abfd,asection * sect,void * arg)344*a9fa9459Szrj strings_a_section (bfd *abfd, asection *sect, void *arg)
345*a9fa9459Szrj {
346*a9fa9459Szrj filename_and_size_t * filename_and_sizep;
347*a9fa9459Szrj bfd_size_type *filesizep;
348*a9fa9459Szrj bfd_size_type sectsize;
349*a9fa9459Szrj void *mem;
350*a9fa9459Szrj
351*a9fa9459Szrj if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
352*a9fa9459Szrj return;
353*a9fa9459Szrj
354*a9fa9459Szrj sectsize = bfd_get_section_size (sect);
355*a9fa9459Szrj
356*a9fa9459Szrj if (sectsize <= 0)
357*a9fa9459Szrj return;
358*a9fa9459Szrj
359*a9fa9459Szrj /* Get the size of the file. This might have been cached for us. */
360*a9fa9459Szrj filename_and_sizep = (filename_and_size_t *) arg;
361*a9fa9459Szrj filesizep = & filename_and_sizep->filesize;
362*a9fa9459Szrj
363*a9fa9459Szrj if (*filesizep == 0)
364*a9fa9459Szrj {
365*a9fa9459Szrj struct stat st;
366*a9fa9459Szrj
367*a9fa9459Szrj if (bfd_stat (abfd, &st))
368*a9fa9459Szrj return;
369*a9fa9459Szrj
370*a9fa9459Szrj /* Cache the result so that we do not repeatedly stat this file. */
371*a9fa9459Szrj *filesizep = st.st_size;
372*a9fa9459Szrj }
373*a9fa9459Szrj
374*a9fa9459Szrj /* Compare the size of the section against the size of the file.
375*a9fa9459Szrj If the section is bigger then the file must be corrupt and
376*a9fa9459Szrj we should not try dumping it. */
377*a9fa9459Szrj if (sectsize >= *filesizep)
378*a9fa9459Szrj return;
379*a9fa9459Szrj
380*a9fa9459Szrj mem = xmalloc (sectsize);
381*a9fa9459Szrj
382*a9fa9459Szrj if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
383*a9fa9459Szrj {
384*a9fa9459Szrj got_a_section = TRUE;
385*a9fa9459Szrj
386*a9fa9459Szrj print_strings (filename_and_sizep->filename, NULL, sect->filepos,
387*a9fa9459Szrj 0, sectsize, (char *) mem);
388*a9fa9459Szrj }
389*a9fa9459Szrj
390*a9fa9459Szrj free (mem);
391*a9fa9459Szrj }
392*a9fa9459Szrj
393*a9fa9459Szrj /* Scan all of the sections in FILE, and print the strings
394*a9fa9459Szrj in the initialized data section(s).
395*a9fa9459Szrj
396*a9fa9459Szrj Return TRUE if successful,
397*a9fa9459Szrj FALSE if not (such as if FILE is not an object file). */
398*a9fa9459Szrj
399*a9fa9459Szrj static bfd_boolean
strings_object_file(const char * file)400*a9fa9459Szrj strings_object_file (const char *file)
401*a9fa9459Szrj {
402*a9fa9459Szrj filename_and_size_t filename_and_size;
403*a9fa9459Szrj bfd *abfd;
404*a9fa9459Szrj
405*a9fa9459Szrj abfd = bfd_openr (file, target);
406*a9fa9459Szrj
407*a9fa9459Szrj if (abfd == NULL)
408*a9fa9459Szrj /* Treat the file as a non-object file. */
409*a9fa9459Szrj return FALSE;
410*a9fa9459Szrj
411*a9fa9459Szrj /* This call is mainly for its side effect of reading in the sections.
412*a9fa9459Szrj We follow the traditional behavior of `strings' in that we don't
413*a9fa9459Szrj complain if we don't recognize a file to be an object file. */
414*a9fa9459Szrj if (!bfd_check_format (abfd, bfd_object))
415*a9fa9459Szrj {
416*a9fa9459Szrj bfd_close (abfd);
417*a9fa9459Szrj return FALSE;
418*a9fa9459Szrj }
419*a9fa9459Szrj
420*a9fa9459Szrj got_a_section = FALSE;
421*a9fa9459Szrj filename_and_size.filename = file;
422*a9fa9459Szrj filename_and_size.filesize = 0;
423*a9fa9459Szrj bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
424*a9fa9459Szrj
425*a9fa9459Szrj if (!bfd_close (abfd))
426*a9fa9459Szrj {
427*a9fa9459Szrj bfd_nonfatal (file);
428*a9fa9459Szrj return FALSE;
429*a9fa9459Szrj }
430*a9fa9459Szrj
431*a9fa9459Szrj return got_a_section;
432*a9fa9459Szrj }
433*a9fa9459Szrj
434*a9fa9459Szrj /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
435*a9fa9459Szrj
436*a9fa9459Szrj static bfd_boolean
strings_file(char * file)437*a9fa9459Szrj strings_file (char *file)
438*a9fa9459Szrj {
439*a9fa9459Szrj struct stat st;
440*a9fa9459Szrj
441*a9fa9459Szrj /* get_file_size does not support non-S_ISREG files. */
442*a9fa9459Szrj
443*a9fa9459Szrj if (stat (file, &st) < 0)
444*a9fa9459Szrj {
445*a9fa9459Szrj if (errno == ENOENT)
446*a9fa9459Szrj non_fatal (_("'%s': No such file"), file);
447*a9fa9459Szrj else
448*a9fa9459Szrj non_fatal (_("Warning: could not locate '%s'. reason: %s"),
449*a9fa9459Szrj file, strerror (errno));
450*a9fa9459Szrj return FALSE;
451*a9fa9459Szrj }
452*a9fa9459Szrj
453*a9fa9459Szrj /* If we weren't told to scan the whole file,
454*a9fa9459Szrj try to open it as an object file and only look at
455*a9fa9459Szrj initialized data sections. If that fails, fall back to the
456*a9fa9459Szrj whole file. */
457*a9fa9459Szrj if (!datasection_only || !strings_object_file (file))
458*a9fa9459Szrj {
459*a9fa9459Szrj FILE *stream;
460*a9fa9459Szrj
461*a9fa9459Szrj stream = fopen (file, FOPEN_RB);
462*a9fa9459Szrj if (stream == NULL)
463*a9fa9459Szrj {
464*a9fa9459Szrj fprintf (stderr, "%s: ", program_name);
465*a9fa9459Szrj perror (file);
466*a9fa9459Szrj return FALSE;
467*a9fa9459Szrj }
468*a9fa9459Szrj
469*a9fa9459Szrj print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
470*a9fa9459Szrj
471*a9fa9459Szrj if (fclose (stream) == EOF)
472*a9fa9459Szrj {
473*a9fa9459Szrj fprintf (stderr, "%s: ", program_name);
474*a9fa9459Szrj perror (file);
475*a9fa9459Szrj return FALSE;
476*a9fa9459Szrj }
477*a9fa9459Szrj }
478*a9fa9459Szrj
479*a9fa9459Szrj return TRUE;
480*a9fa9459Szrj }
481*a9fa9459Szrj
482*a9fa9459Szrj /* Read the next character, return EOF if none available.
483*a9fa9459Szrj Assume that STREAM is positioned so that the next byte read
484*a9fa9459Szrj is at address ADDRESS in the file.
485*a9fa9459Szrj
486*a9fa9459Szrj If STREAM is NULL, do not read from it.
487*a9fa9459Szrj The caller can supply a buffer of characters
488*a9fa9459Szrj to be processed before the data in STREAM.
489*a9fa9459Szrj MAGIC is the address of the buffer and
490*a9fa9459Szrj MAGICCOUNT is how many characters are in it. */
491*a9fa9459Szrj
492*a9fa9459Szrj static long
get_char(FILE * stream,file_ptr * address,int * magiccount,char ** magic)493*a9fa9459Szrj get_char (FILE *stream, file_ptr *address, int *magiccount, char **magic)
494*a9fa9459Szrj {
495*a9fa9459Szrj int c, i;
496*a9fa9459Szrj long r = 0;
497*a9fa9459Szrj
498*a9fa9459Szrj for (i = 0; i < encoding_bytes; i++)
499*a9fa9459Szrj {
500*a9fa9459Szrj if (*magiccount)
501*a9fa9459Szrj {
502*a9fa9459Szrj (*magiccount)--;
503*a9fa9459Szrj c = *(*magic)++;
504*a9fa9459Szrj }
505*a9fa9459Szrj else
506*a9fa9459Szrj {
507*a9fa9459Szrj if (stream == NULL)
508*a9fa9459Szrj return EOF;
509*a9fa9459Szrj
510*a9fa9459Szrj /* Only use getc_unlocked if we found a declaration for it.
511*a9fa9459Szrj Otherwise, libc is not thread safe by default, and we
512*a9fa9459Szrj should not use it. */
513*a9fa9459Szrj
514*a9fa9459Szrj #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
515*a9fa9459Szrj c = getc_unlocked (stream);
516*a9fa9459Szrj #else
517*a9fa9459Szrj c = getc (stream);
518*a9fa9459Szrj #endif
519*a9fa9459Szrj if (c == EOF)
520*a9fa9459Szrj return EOF;
521*a9fa9459Szrj }
522*a9fa9459Szrj
523*a9fa9459Szrj (*address)++;
524*a9fa9459Szrj r = (r << 8) | (c & 0xff);
525*a9fa9459Szrj }
526*a9fa9459Szrj
527*a9fa9459Szrj switch (encoding)
528*a9fa9459Szrj {
529*a9fa9459Szrj default:
530*a9fa9459Szrj break;
531*a9fa9459Szrj case 'l':
532*a9fa9459Szrj r = ((r & 0xff) << 8) | ((r & 0xff00) >> 8);
533*a9fa9459Szrj break;
534*a9fa9459Szrj case 'L':
535*a9fa9459Szrj r = (((r & 0xff) << 24) | ((r & 0xff00) << 8)
536*a9fa9459Szrj | ((r & 0xff0000) >> 8) | ((r & 0xff000000) >> 24));
537*a9fa9459Szrj break;
538*a9fa9459Szrj }
539*a9fa9459Szrj
540*a9fa9459Szrj return r;
541*a9fa9459Szrj }
542*a9fa9459Szrj
543*a9fa9459Szrj /* Find the strings in file FILENAME, read from STREAM.
544*a9fa9459Szrj Assume that STREAM is positioned so that the next byte read
545*a9fa9459Szrj is at address ADDRESS in the file.
546*a9fa9459Szrj Stop reading at address STOP_POINT in the file, if nonzero.
547*a9fa9459Szrj
548*a9fa9459Szrj If STREAM is NULL, do not read from it.
549*a9fa9459Szrj The caller can supply a buffer of characters
550*a9fa9459Szrj to be processed before the data in STREAM.
551*a9fa9459Szrj MAGIC is the address of the buffer and
552*a9fa9459Szrj MAGICCOUNT is how many characters are in it.
553*a9fa9459Szrj Those characters come at address ADDRESS and the data in STREAM follow. */
554*a9fa9459Szrj
555*a9fa9459Szrj static void
print_strings(const char * filename,FILE * stream,file_ptr address,int stop_point,int magiccount,char * magic)556*a9fa9459Szrj print_strings (const char *filename, FILE *stream, file_ptr address,
557*a9fa9459Szrj int stop_point, int magiccount, char *magic)
558*a9fa9459Szrj {
559*a9fa9459Szrj char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
560*a9fa9459Szrj
561*a9fa9459Szrj while (1)
562*a9fa9459Szrj {
563*a9fa9459Szrj file_ptr start;
564*a9fa9459Szrj int i;
565*a9fa9459Szrj long c;
566*a9fa9459Szrj
567*a9fa9459Szrj /* See if the next `string_min' chars are all graphic chars. */
568*a9fa9459Szrj tryline:
569*a9fa9459Szrj if (stop_point && address >= stop_point)
570*a9fa9459Szrj break;
571*a9fa9459Szrj start = address;
572*a9fa9459Szrj for (i = 0; i < string_min; i++)
573*a9fa9459Szrj {
574*a9fa9459Szrj c = get_char (stream, &address, &magiccount, &magic);
575*a9fa9459Szrj if (c == EOF)
576*a9fa9459Szrj {
577*a9fa9459Szrj free (buf);
578*a9fa9459Szrj return;
579*a9fa9459Szrj }
580*a9fa9459Szrj if (! STRING_ISGRAPHIC (c))
581*a9fa9459Szrj /* Found a non-graphic. Try again starting with next char. */
582*a9fa9459Szrj goto tryline;
583*a9fa9459Szrj buf[i] = c;
584*a9fa9459Szrj }
585*a9fa9459Szrj
586*a9fa9459Szrj /* We found a run of `string_min' graphic characters. Print up
587*a9fa9459Szrj to the next non-graphic character. */
588*a9fa9459Szrj
589*a9fa9459Szrj if (print_filenames)
590*a9fa9459Szrj printf ("%s: ", filename);
591*a9fa9459Szrj if (print_addresses)
592*a9fa9459Szrj switch (address_radix)
593*a9fa9459Szrj {
594*a9fa9459Szrj case 8:
595*a9fa9459Szrj #ifdef HAVE_LONG_LONG
596*a9fa9459Szrj if (sizeof (start) > sizeof (long))
597*a9fa9459Szrj {
598*a9fa9459Szrj # ifndef __MSVCRT__
599*a9fa9459Szrj printf ("%7llo ", (unsigned long long) start);
600*a9fa9459Szrj # else
601*a9fa9459Szrj printf ("%7I64o ", (unsigned long long) start);
602*a9fa9459Szrj # endif
603*a9fa9459Szrj }
604*a9fa9459Szrj else
605*a9fa9459Szrj #elif !BFD_HOST_64BIT_LONG
606*a9fa9459Szrj if (start != (unsigned long) start)
607*a9fa9459Szrj printf ("++%7lo ", (unsigned long) start);
608*a9fa9459Szrj else
609*a9fa9459Szrj #endif
610*a9fa9459Szrj printf ("%7lo ", (unsigned long) start);
611*a9fa9459Szrj break;
612*a9fa9459Szrj
613*a9fa9459Szrj case 10:
614*a9fa9459Szrj #ifdef HAVE_LONG_LONG
615*a9fa9459Szrj if (sizeof (start) > sizeof (long))
616*a9fa9459Szrj {
617*a9fa9459Szrj # ifndef __MSVCRT__
618*a9fa9459Szrj printf ("%7lld ", (unsigned long long) start);
619*a9fa9459Szrj # else
620*a9fa9459Szrj printf ("%7I64d ", (unsigned long long) start);
621*a9fa9459Szrj # endif
622*a9fa9459Szrj }
623*a9fa9459Szrj else
624*a9fa9459Szrj #elif !BFD_HOST_64BIT_LONG
625*a9fa9459Szrj if (start != (unsigned long) start)
626*a9fa9459Szrj printf ("++%7ld ", (unsigned long) start);
627*a9fa9459Szrj else
628*a9fa9459Szrj #endif
629*a9fa9459Szrj printf ("%7ld ", (long) start);
630*a9fa9459Szrj break;
631*a9fa9459Szrj
632*a9fa9459Szrj case 16:
633*a9fa9459Szrj #ifdef HAVE_LONG_LONG
634*a9fa9459Szrj if (sizeof (start) > sizeof (long))
635*a9fa9459Szrj {
636*a9fa9459Szrj # ifndef __MSVCRT__
637*a9fa9459Szrj printf ("%7llx ", (unsigned long long) start);
638*a9fa9459Szrj # else
639*a9fa9459Szrj printf ("%7I64x ", (unsigned long long) start);
640*a9fa9459Szrj # endif
641*a9fa9459Szrj }
642*a9fa9459Szrj else
643*a9fa9459Szrj #elif !BFD_HOST_64BIT_LONG
644*a9fa9459Szrj if (start != (unsigned long) start)
645*a9fa9459Szrj printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
646*a9fa9459Szrj (unsigned long) (start & 0xffffffff));
647*a9fa9459Szrj else
648*a9fa9459Szrj #endif
649*a9fa9459Szrj printf ("%7lx ", (unsigned long) start);
650*a9fa9459Szrj break;
651*a9fa9459Szrj }
652*a9fa9459Szrj
653*a9fa9459Szrj buf[i] = '\0';
654*a9fa9459Szrj fputs (buf, stdout);
655*a9fa9459Szrj
656*a9fa9459Szrj while (1)
657*a9fa9459Szrj {
658*a9fa9459Szrj c = get_char (stream, &address, &magiccount, &magic);
659*a9fa9459Szrj if (c == EOF)
660*a9fa9459Szrj break;
661*a9fa9459Szrj if (! STRING_ISGRAPHIC (c))
662*a9fa9459Szrj break;
663*a9fa9459Szrj putchar (c);
664*a9fa9459Szrj }
665*a9fa9459Szrj
666*a9fa9459Szrj if (output_separator)
667*a9fa9459Szrj fputs (output_separator, stdout);
668*a9fa9459Szrj else
669*a9fa9459Szrj putchar ('\n');
670*a9fa9459Szrj }
671*a9fa9459Szrj free (buf);
672*a9fa9459Szrj }
673*a9fa9459Szrj
674*a9fa9459Szrj static void
usage(FILE * stream,int status)675*a9fa9459Szrj usage (FILE *stream, int status)
676*a9fa9459Szrj {
677*a9fa9459Szrj fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
678*a9fa9459Szrj fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
679*a9fa9459Szrj fprintf (stream, _(" The options are:\n"));
680*a9fa9459Szrj
681*a9fa9459Szrj if (DEFAULT_STRINGS_ALL)
682*a9fa9459Szrj fprintf (stream, _("\
683*a9fa9459Szrj -a - --all Scan the entire file, not just the data section [default]\n\
684*a9fa9459Szrj -d --data Only scan the data sections in the file\n"));
685*a9fa9459Szrj else
686*a9fa9459Szrj fprintf (stream, _("\
687*a9fa9459Szrj -a - --all Scan the entire file, not just the data section\n\
688*a9fa9459Szrj -d --data Only scan the data sections in the file [default]\n"));
689*a9fa9459Szrj
690*a9fa9459Szrj fprintf (stream, _("\
691*a9fa9459Szrj -f --print-file-name Print the name of the file before each string\n\
692*a9fa9459Szrj -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
693*a9fa9459Szrj -<number> least [number] characters (default 4).\n\
694*a9fa9459Szrj -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
695*a9fa9459Szrj -w --include-all-whitespace Include all whitespace as valid string characters\n\
696*a9fa9459Szrj -o An alias for --radix=o\n\
697*a9fa9459Szrj -T --target=<BFDNAME> Specify the binary file format\n\
698*a9fa9459Szrj -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
699*a9fa9459Szrj s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
700*a9fa9459Szrj -s --output-separator=<string> String used to separate strings in output.\n\
701*a9fa9459Szrj @<file> Read options from <file>\n\
702*a9fa9459Szrj -h --help Display this information\n\
703*a9fa9459Szrj -v -V --version Print the program's version number\n"));
704*a9fa9459Szrj list_supported_targets (program_name, stream);
705*a9fa9459Szrj if (REPORT_BUGS_TO[0] && status == 0)
706*a9fa9459Szrj fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
707*a9fa9459Szrj exit (status);
708*a9fa9459Szrj }
709