xref: /dflybsd-src/contrib/binutils-2.27/binutils/strings.c (revision e656dc90e3d65d744d534af2f5ea88cf8101ebcf)
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