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