* ltconfig, ltmain.sh, libtool.m4, ltcf-c.sh, ltcf-cxx.sh,
[deliverable/binutils-gdb.git] / binutils / strings.c
1 /* strings -- print the strings of printable characters in files
2 Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
3 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA. */
19 \f
20 /* Usage: strings [options] file...
21
22 Options:
23 --all
24 -a
25 - Do not scan only the initialized data section of object files.
26
27 --print-file-name
28 -f Print the name of the file before each string.
29
30 --bytes=min-len
31 -n min-len
32 -min-len Print graphic char sequences, MIN-LEN or more bytes long,
33 that are followed by a NUL or a newline. Default is 4.
34
35 --radix={o,x,d}
36 -t {o,x,d} Print the offset within the file before each string,
37 in octal/hex/decimal.
38
39 -o Like -to. (Some other implementations have -o like -to,
40 others like -td. We chose one arbitrarily.)
41
42 --target=BFDNAME
43 Specify a non-default object file format.
44
45 --help
46 -h Print the usage message on the standard output.
47
48 --version
49 -v Print the program version number.
50
51 Written by Richard Stallman <rms@gnu.ai.mit.edu>
52 and David MacKenzie <djm@gnu.ai.mit.edu>. */
53
54 #include "bfd.h"
55 #include <stdio.h>
56 #include <getopt.h>
57 #include <ctype.h>
58 #include <errno.h>
59 #include "bucomm.h"
60 #include "libiberty.h"
61
62 /* Some platforms need to put stdin into binary mode, to read
63 binary files. */
64 #ifdef HAVE_SETMODE
65 #ifndef O_BINARY
66 #ifdef _O_BINARY
67 #define O_BINARY _O_BINARY
68 #define setmode _setmode
69 #else
70 #define O_BINARY 0
71 #endif
72 #endif
73 #if O_BINARY
74 #include <io.h>
75 #define SET_BINARY(f) do { if (!isatty(f)) setmode(f,O_BINARY); } while (0)
76 #endif
77 #endif
78
79 /* Not all printable characters have ASCII codes (depending upon the
80 LOCALE set) but on some older systems it is not safe to test isprint
81 without first testing isascii... */
82 #if defined isascii && !defined HAVE_LOCALE_H
83 #define isgraphic(c) (isascii (c) && (isprint (c) || (c) == '\t'))
84 #else
85 #define isgraphic(c) (isprint (c) || (c) == '\t')
86 #endif
87
88 #ifndef errno
89 extern int errno;
90 #endif
91
92 /* The BFD section flags that identify an initialized data section. */
93 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
94
95 /* Radix for printing addresses (must be 8, 10 or 16). */
96 static int address_radix;
97
98 /* Minimum length of sequence of graphic chars to trigger output. */
99 static int string_min;
100
101 /* true means print address within file for each string. */
102 static boolean print_addresses;
103
104 /* true means print filename for each string. */
105 static boolean print_filenames;
106
107 /* true means for object files scan only the data section. */
108 static boolean datasection_only;
109
110 /* true if we found an initialized data section in the current file. */
111 static boolean got_a_section;
112
113 /* The BFD object file format. */
114 static char *target;
115
116 static struct option long_options[] =
117 {
118 {"all", no_argument, NULL, 'a'},
119 {"print-file-name", no_argument, NULL, 'f'},
120 {"bytes", required_argument, NULL, 'n'},
121 {"radix", required_argument, NULL, 't'},
122 {"target", required_argument, NULL, 'T'},
123 {"help", no_argument, NULL, 'h'},
124 {"version", no_argument, NULL, 'v'},
125 {NULL, 0, NULL, 0}
126 };
127
128 static void strings_a_section PARAMS ((bfd *, asection *, PTR));
129 static boolean strings_object_file PARAMS ((const char *));
130 static boolean strings_file PARAMS ((char *file));
131 static int integer_arg PARAMS ((char *s));
132 static void print_strings PARAMS ((const char *filename, FILE *stream,
133 file_ptr address, int stop_point,
134 int magiccount, char *magic));
135 static void usage PARAMS ((FILE *stream, int status));
136 \f
137 int
138 main (argc, argv)
139 int argc;
140 char **argv;
141 {
142 int optc;
143 int exit_status = 0;
144 boolean files_given = false;
145
146 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
147 setlocale (LC_ALL, "");
148 #endif
149 bindtextdomain (PACKAGE, LOCALEDIR);
150 textdomain (PACKAGE);
151
152 program_name = argv[0];
153 xmalloc_set_program_name (program_name);
154 string_min = -1;
155 print_addresses = false;
156 print_filenames = false;
157 datasection_only = true;
158 target = NULL;
159
160 while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789",
161 long_options, (int *) 0)) != EOF)
162 {
163 switch (optc)
164 {
165 case 'a':
166 datasection_only = false;
167 break;
168
169 case 'f':
170 print_filenames = true;
171 break;
172
173 case 'h':
174 usage (stdout, 0);
175
176 case 'n':
177 string_min = integer_arg (optarg);
178 if (string_min < 1)
179 {
180 fatal (_("invalid number %s"), optarg);
181 }
182 break;
183
184 case 'o':
185 print_addresses = true;
186 address_radix = 8;
187 break;
188
189 case 't':
190 print_addresses = true;
191 if (optarg[1] != '\0')
192 usage (stderr, 1);
193 switch (optarg[0])
194 {
195 case 'o':
196 address_radix = 8;
197 break;
198
199 case 'd':
200 address_radix = 10;
201 break;
202
203 case 'x':
204 address_radix = 16;
205 break;
206
207 default:
208 usage (stderr, 1);
209 }
210 break;
211
212 case 'T':
213 target = optarg;
214 break;
215
216 case 'v':
217 print_version ("strings");
218 break;
219
220 case '?':
221 usage (stderr, 1);
222
223 default:
224 if (string_min < 0)
225 string_min = optc - '0';
226 else
227 string_min = string_min * 10 + optc - '0';
228 break;
229 }
230 }
231
232 if (string_min < 0)
233 string_min = 4;
234
235 bfd_init ();
236 set_default_bfd_target ();
237
238 if (optind >= argc)
239 {
240 datasection_only = false;
241 #ifdef SET_BINARY
242 SET_BINARY (fileno (stdin));
243 #endif
244 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
245 files_given = true;
246 }
247 else
248 {
249 for (; optind < argc; ++optind)
250 {
251 if (strcmp (argv[optind], "-") == 0)
252 datasection_only = false;
253 else
254 {
255 files_given = true;
256 exit_status |= (strings_file (argv[optind]) == false);
257 }
258 }
259 }
260
261 if (files_given == false)
262 usage (stderr, 1);
263
264 return (exit_status);
265 }
266 \f
267 /* Scan section SECT of the file ABFD, whose printable name is FILE.
268 If it contains initialized data,
269 set `got_a_section' and print the strings in it. */
270
271 static void
272 strings_a_section (abfd, sect, filearg)
273 bfd *abfd;
274 asection *sect;
275 PTR filearg;
276 {
277 const char *file = (const char *) filearg;
278
279 if ((sect->flags & DATA_FLAGS) == DATA_FLAGS)
280 {
281 bfd_size_type sz = bfd_get_section_size_before_reloc (sect);
282 PTR mem = xmalloc (sz);
283 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz))
284 {
285 got_a_section = true;
286 print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
287 }
288 free (mem);
289 }
290 }
291
292 /* Scan all of the sections in FILE, and print the strings
293 in the initialized data section(s).
294
295 Return true if successful,
296 false if not (such as if FILE is not an object file). */
297
298 static boolean
299 strings_object_file (file)
300 const char *file;
301 {
302 bfd *abfd = bfd_openr (file, target);
303
304 if (abfd == NULL)
305 {
306 /* Treat the file as a non-object file. */
307 return false;
308 }
309
310 /* This call is mainly for its side effect of reading in the sections.
311 We follow the traditional behavior of `strings' in that we don't
312 complain if we don't recognize a file to be an object file. */
313 if (bfd_check_format (abfd, bfd_object) == false)
314 {
315 bfd_close (abfd);
316 return false;
317 }
318
319 got_a_section = false;
320 bfd_map_over_sections (abfd, strings_a_section, (PTR) file);
321
322 if (!bfd_close (abfd))
323 {
324 bfd_nonfatal (file);
325 return false;
326 }
327
328 return got_a_section;
329 }
330
331 /* Print the strings in FILE. Return true if ok, false if an error occurs. */
332
333 static boolean
334 strings_file (file)
335 char *file;
336 {
337 /* If we weren't told to scan the whole file,
338 try to open it as an object file and only look at
339 initialized data sections. If that fails, fall back to the
340 whole file. */
341 if (!datasection_only || !strings_object_file (file))
342 {
343 FILE *stream;
344
345 stream = fopen (file, "rb");
346 /* Not all systems permit "rb", so try "r" if it failed. */
347 if (stream == NULL)
348 stream = fopen (file, "r");
349 if (stream == NULL)
350 {
351 fprintf (stderr, "%s: ", program_name);
352 perror (file);
353 return false;
354 }
355
356 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
357
358 if (fclose (stream) == EOF)
359 {
360 fprintf (stderr, "%s: ", program_name);
361 perror (file);
362 return false;
363 }
364 }
365
366 return true;
367 }
368 \f
369 /* Find the strings in file FILENAME, read from STREAM.
370 Assume that STREAM is positioned so that the next byte read
371 is at address ADDRESS in the file.
372 Stop reading at address STOP_POINT in the file, if nonzero.
373
374 If STREAM is NULL, do not read from it.
375 The caller can supply a buffer of characters
376 to be processed before the data in STREAM.
377 MAGIC is the address of the buffer and
378 MAGICCOUNT is how many characters are in it.
379 Those characters come at address ADDRESS and the data in STREAM follow. */
380
381 static void
382 print_strings (filename, stream, address, stop_point, magiccount, magic)
383 const char *filename;
384 FILE *stream;
385 file_ptr address;
386 int stop_point;
387 int magiccount;
388 char *magic;
389 {
390 char *buf = (char *) xmalloc (string_min + 1);
391
392 while (1)
393 {
394 file_ptr start;
395 int i;
396 int c;
397
398 /* See if the next `string_min' chars are all graphic chars. */
399 tryline:
400 if (stop_point && address >= stop_point)
401 break;
402 start = address;
403 for (i = 0; i < string_min; i++)
404 {
405 if (magiccount)
406 {
407 magiccount--;
408 c = *magic++;
409 }
410 else
411 {
412 if (stream == NULL)
413 return;
414 c = getc (stream);
415 if (c == EOF)
416 return;
417 }
418 address++;
419 if (!isgraphic (c))
420 /* Found a non-graphic. Try again starting with next char. */
421 goto tryline;
422 buf[i] = c;
423 }
424
425 /* We found a run of `string_min' graphic characters. Print up
426 to the next non-graphic character. */
427
428 if (print_filenames)
429 printf ("%s: ", filename);
430 if (print_addresses)
431 switch (address_radix)
432 {
433 case 8:
434 printf ("%7lo ", (unsigned long) start);
435 break;
436
437 case 10:
438 printf ("%7ld ", (long) start);
439 break;
440
441 case 16:
442 printf ("%7lx ", (unsigned long) start);
443 break;
444 }
445
446 buf[i] = '\0';
447 fputs (buf, stdout);
448
449 while (1)
450 {
451 if (magiccount)
452 {
453 magiccount--;
454 c = *magic++;
455 }
456 else
457 {
458 if (stream == NULL)
459 break;
460 c = getc (stream);
461 if (c == EOF)
462 break;
463 }
464 address++;
465 if (! isgraphic (c))
466 break;
467 putchar (c);
468 }
469
470 putchar ('\n');
471 }
472 }
473 \f
474 /* Parse string S as an integer, using decimal radix by default,
475 but allowing octal and hex numbers as in C. */
476
477 static int
478 integer_arg (s)
479 char *s;
480 {
481 int value;
482 int radix = 10;
483 char *p = s;
484 int c;
485
486 if (*p != '0')
487 radix = 10;
488 else if (*++p == 'x')
489 {
490 radix = 16;
491 p++;
492 }
493 else
494 radix = 8;
495
496 value = 0;
497 while (((c = *p++) >= '0' && c <= '9')
498 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
499 {
500 value *= radix;
501 if (c >= '0' && c <= '9')
502 value += c - '0';
503 else
504 value += (c & ~40) - 'A';
505 }
506
507 if (c == 'b')
508 value *= 512;
509 else if (c == 'B')
510 value *= 1024;
511 else
512 p--;
513
514 if (*p)
515 {
516 fatal (_("invalid integer argument %s"), s);
517 }
518 return value;
519 }
520
521 static void
522 usage (stream, status)
523 FILE *stream;
524 int status;
525 {
526 fprintf (stream, _("\
527 Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\
528 [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
529 [--target=bfdname] [--help] [--version] file...\n"),
530 program_name);
531 list_supported_targets (program_name, stream);
532 if (status == 0)
533 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
534 exit (status);
535 }
This page took 0.055461 seconds and 4 git commands to generate.