Forgot to remove this file from .Sanitize.
[deliverable/binutils-gdb.git] / binutils / strings.c
1 /* strings -- print the strings of printable characters in files
2 Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
3
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)
7 any later version.
8
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.
13
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
17 02111-1307, USA. */
18 \f
19 /* Usage: strings [options] file...
20
21 Options:
22 --all
23 -a
24 - Do not scan only the initialized data section of object files.
25
26 --print-file-name
27 -f Print the name of the file before each string.
28
29 --bytes=min-len
30 -n min-len
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.
33
34 --radix={o,x,d}
35 -t {o,x,d} Print the offset within the file before each string,
36 in octal/hex/decimal.
37
38 -o Like -to. (Some other implementations have -o like -to,
39 others like -td. We chose one arbitrarily.)
40
41 --target=BFDNAME
42 Specify a non-default object file format.
43
44 --help
45 -h Print the usage message on the standard output.
46
47 --version
48 -v Print the program version number.
49
50 Written by Richard Stallman <rms@gnu.ai.mit.edu>
51 and David MacKenzie <djm@gnu.ai.mit.edu>. */
52
53 #include "bfd.h"
54 #include <stdio.h>
55 #include <getopt.h>
56 #include <ctype.h>
57 #include <errno.h>
58 #include "bucomm.h"
59 #include "libiberty.h"
60
61 #ifdef isascii
62 #define isgraphic(c) (isascii (c) && isprint (c))
63 #else
64 #define isgraphic(c) (isprint (c))
65 #endif
66
67 #ifndef errno
68 extern int errno;
69 #endif
70
71 /* The BFD section flags that identify an initialized data section. */
72 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
73
74 /* Radix for printing addresses (must be 8, 10 or 16). */
75 static int address_radix;
76
77 /* Minimum length of sequence of graphic chars to trigger output. */
78 static int string_min;
79
80 /* true means print address within file for each string. */
81 static boolean print_addresses;
82
83 /* true means print filename for each string. */
84 static boolean print_filenames;
85
86 /* true means for object files scan only the data section. */
87 static boolean datasection_only;
88
89 /* true if we found an initialized data section in the current file. */
90 static boolean got_a_section;
91
92 /* The BFD object file format. */
93 static char *target;
94
95 static struct option long_options[] =
96 {
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'},
104 {NULL, 0, NULL, 0}
105 };
106
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));
115 \f
116 int
117 main (argc, argv)
118 int argc;
119 char **argv;
120 {
121 int optc;
122 int exit_status = 0;
123 boolean files_given = false;
124
125 setlocale (LC_MESSAGES, "");
126 bindtextdomain (PACKAGE, LOCALEDIR);
127 textdomain (PACKAGE);
128
129 program_name = argv[0];
130 xmalloc_set_program_name (program_name);
131 string_min = -1;
132 print_addresses = false;
133 print_filenames = false;
134 datasection_only = true;
135 target = NULL;
136
137 while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789",
138 long_options, (int *) 0)) != EOF)
139 {
140 switch (optc)
141 {
142 case 'a':
143 datasection_only = false;
144 break;
145
146 case 'f':
147 print_filenames = true;
148 break;
149
150 case 'h':
151 usage (stdout, 0);
152
153 case 'n':
154 string_min = integer_arg (optarg);
155 if (string_min < 1)
156 {
157 fprintf (stderr, _("%s: invalid number %s\n"),
158 program_name, optarg);
159 exit (1);
160 }
161 break;
162
163 case 'o':
164 print_addresses = true;
165 address_radix = 8;
166 break;
167
168 case 't':
169 print_addresses = true;
170 if (optarg[1] != '\0')
171 usage (stderr, 1);
172 switch (optarg[0])
173 {
174 case 'o':
175 address_radix = 8;
176 break;
177
178 case 'd':
179 address_radix = 10;
180 break;
181
182 case 'x':
183 address_radix = 16;
184 break;
185
186 default:
187 usage (stderr, 1);
188 }
189 break;
190
191 case 'T':
192 target = optarg;
193 break;
194
195 case 'v':
196 print_version ("strings");
197 break;
198
199 case '?':
200 usage (stderr, 1);
201
202 default:
203 if (string_min < 0)
204 string_min = optc;
205 else
206 string_min = string_min * 10 + optc - '0';
207 break;
208 }
209 }
210
211 if (string_min < 0)
212 string_min = 4;
213
214 bfd_init ();
215 set_default_bfd_target ();
216
217 if (optind >= argc)
218 {
219 datasection_only = false;
220 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
221 files_given = true;
222 }
223 else
224 {
225 for (; optind < argc; ++optind)
226 {
227 if (strcmp (argv[optind], "-") == 0)
228 datasection_only = false;
229 else
230 {
231 files_given = true;
232 exit_status |= (strings_file (argv[optind]) == false);
233 }
234 }
235 }
236
237 if (files_given == false)
238 usage (stderr, 1);
239
240 return (exit_status);
241 }
242 \f
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. */
246
247 static void
248 strings_a_section (abfd, sect, filearg)
249 bfd *abfd;
250 asection *sect;
251 PTR filearg;
252 {
253 const char *file = (const char *) filearg;
254
255 if ((sect->flags & DATA_FLAGS) == DATA_FLAGS)
256 {
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))
260 {
261 got_a_section = true;
262 print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
263 }
264 free (mem);
265 }
266 }
267
268 /* Scan all of the sections in FILE, and print the strings
269 in the initialized data section(s).
270
271 Return true if successful,
272 false if not (such as if FILE is not an object file). */
273
274 static boolean
275 strings_object_file (file)
276 const char *file;
277 {
278 bfd *abfd = bfd_openr (file, target);
279
280 if (abfd == NULL)
281 {
282 /* Treat the file as a non-object file. */
283 return false;
284 }
285
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)
290 {
291 bfd_close (abfd);
292 return false;
293 }
294
295 got_a_section = false;
296 bfd_map_over_sections (abfd, strings_a_section, (PTR) file);
297
298 if (!bfd_close (abfd))
299 {
300 bfd_nonfatal (file);
301 return false;
302 }
303
304 return got_a_section;
305 }
306
307 /* Print the strings in FILE. Return true if ok, false if an error occurs. */
308
309 static boolean
310 strings_file (file)
311 char *file;
312 {
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
316 whole file. */
317 if (!datasection_only || !strings_object_file (file))
318 {
319 FILE *stream;
320
321 stream = fopen (file, "rb");
322 /* Not all systems permit "rb", so try "r" if it failed. */
323 if (stream == NULL)
324 stream = fopen (file, "r");
325 if (stream == NULL)
326 {
327 fprintf (stderr, "%s: ", program_name);
328 perror (file);
329 return false;
330 }
331
332 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
333
334 if (fclose (stream) == EOF)
335 {
336 fprintf (stderr, "%s: ", program_name);
337 perror (file);
338 return false;
339 }
340 }
341
342 return true;
343 }
344 \f
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.
349
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. */
356
357 static void
358 print_strings (filename, stream, address, stop_point, magiccount, magic)
359 const char *filename;
360 FILE *stream;
361 file_ptr address;
362 int stop_point;
363 int magiccount;
364 char *magic;
365 {
366 char *buf = (char *) xmalloc (string_min + 1);
367
368 while (1)
369 {
370 file_ptr start;
371 int i;
372 int c;
373
374 /* See if the next `string_min' chars are all graphic chars. */
375 tryline:
376 if (stop_point && address >= stop_point)
377 break;
378 start = address;
379 for (i = 0; i < string_min; i++)
380 {
381 if (magiccount)
382 {
383 magiccount--;
384 c = *magic++;
385 }
386 else
387 {
388 if (stream == NULL)
389 return;
390 c = getc (stream);
391 if (c == EOF)
392 return;
393 }
394 address++;
395 if (!isgraphic (c))
396 /* Found a non-graphic. Try again starting with next char. */
397 goto tryline;
398 buf[i] = c;
399 }
400
401 /* We found a run of `string_min' graphic characters. Print up
402 to the next non-graphic character. */
403
404 if (print_filenames)
405 printf ("%s: ", filename);
406 if (print_addresses)
407 switch (address_radix)
408 {
409 case 8:
410 printf ("%7lo ", (unsigned long) start);
411 break;
412
413 case 10:
414 printf ("%7ld ", (long) start);
415 break;
416
417 case 16:
418 printf ("%7lx ", (unsigned long) start);
419 break;
420 }
421
422 buf[i] = '\0';
423 fputs (buf, stdout);
424
425 while (1)
426 {
427 if (magiccount)
428 {
429 magiccount--;
430 c = *magic++;
431 }
432 else
433 {
434 if (stream == NULL)
435 break;
436 c = getc (stream);
437 if (c == EOF)
438 break;
439 }
440 address++;
441 if (! isgraphic (c))
442 break;
443 putchar (c);
444 }
445
446 putchar ('\n');
447 }
448 }
449 \f
450 /* Parse string S as an integer, using decimal radix by default,
451 but allowing octal and hex numbers as in C. */
452
453 static int
454 integer_arg (s)
455 char *s;
456 {
457 int value;
458 int radix = 10;
459 char *p = s;
460 int c;
461
462 if (*p != '0')
463 radix = 10;
464 else if (*++p == 'x')
465 {
466 radix = 16;
467 p++;
468 }
469 else
470 radix = 8;
471
472 value = 0;
473 while (((c = *p++) >= '0' && c <= '9')
474 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
475 {
476 value *= radix;
477 if (c >= '0' && c <= '9')
478 value += c - '0';
479 else
480 value += (c & ~40) - 'A';
481 }
482
483 if (c == 'b')
484 value *= 512;
485 else if (c == 'B')
486 value *= 1024;
487 else
488 p--;
489
490 if (*p)
491 {
492 fprintf (stderr, _("%s: invalid integer argument %s\n"), program_name, s);
493 exit (1);
494 }
495 return value;
496 }
497
498 static void
499 usage (stream, status)
500 FILE *stream;
501 int status;
502 {
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"),
507 program_name);
508 list_supported_targets (program_name, stream);
509 if (status == 0)
510 fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
511 exit (status);
512 }
This page took 0.039918 seconds and 4 git commands to generate.