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