* objdump.c (dump_section_header): Display load address after virtual memory
[deliverable/binutils-gdb.git] / binutils / strings.c
CommitLineData
ba7c8e29 1/* strings -- print the strings of printable characters in files
cef35d48 2 Copyright (C) 1993, 94 Free Software Foundation, Inc.
ba7c8e29
DM
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
cef35d48
DM
40 --target=BFDNAME
41 Specify a non-default object file format.
42
ba7c8e29
DM
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>
2470e6fa
DM
56#include "bfd.h"
57#include "bucomm.h"
ba7c8e29
DM
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
66extern 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). */
73static int address_radix;
74
75/* Minimum length of sequence of graphic chars to trigger output. */
76static int string_min;
77
78/* true means print address within file for each string. */
79static boolean print_addresses;
80
81/* true means print filename for each string. */
82static boolean print_filenames;
83
84/* true means for object files scan only the data section. */
85static boolean datasection_only;
86
87/* true if we found an initialized data section in the current file. */
88static boolean got_a_section;
89
cef35d48
DM
90/* The BFD object file format. */
91static char *target;
ba7c8e29 92
ba7c8e29
DM
93extern char *program_version;
94
95static 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'},
cef35d48 101 {"target", required_argument, NULL, 'T'},
ba7c8e29
DM
102 {"help", no_argument, NULL, 'h'},
103 {"version", no_argument, NULL, 'v'},
104 {NULL, 0, NULL, 0}
105};
106
2470e6fa
DM
107static boolean strings_file PARAMS ((char *file));
108static int integer_arg PARAMS ((char *s));
109static void print_strings PARAMS ((char *filename, FILE *stream,
110 file_ptr address, int stop_point,
111 int magiccount, char *magic));
112static void usage PARAMS ((FILE *stream, int status));
ba7c8e29
DM
113\f
114void
115main (argc, argv)
116 int argc;
117 char **argv;
118{
119 int optc;
120 int exit_status = 0;
fa021947 121 boolean files_given = false;
ba7c8e29
DM
122
123 program_name = argv[0];
124 string_min = -1;
125 print_addresses = false;
126 print_filenames = false;
127 datasection_only = true;
cef35d48 128 target = NULL;
ba7c8e29 129
2470e6fa 130 while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789",
ba7c8e29
DM
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':
2470e6fa 144 usage (stdout, 0);
ba7c8e29
DM
145
146 case 'n':
147 string_min = integer_arg (optarg);
148 if (string_min < 1)
149 {
fa021947
DM
150 fprintf (stderr, "%s: invalid number %s\n",
151 program_name, optarg);
ba7c8e29
DM
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')
2470e6fa 164 usage (stderr, 1);
ba7c8e29
DM
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:
2470e6fa 180 usage (stderr, 1);
ba7c8e29
DM
181 }
182 break;
183
cef35d48
DM
184 case 'T':
185 target = optarg;
186 break;
187
ba7c8e29 188 case 'v':
2470e6fa 189 printf ("GNU %s version %s\n", program_name, program_version);
ba7c8e29
DM
190 exit (0);
191
192 case '?':
2470e6fa 193 usage (stderr, 1);
ba7c8e29
DM
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 ();
ba7c8e29
DM
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)
2470e6fa 221 usage (stderr, 1);
ba7c8e29
DM
222
223 exit (exit_status);
224}
225\f
2470e6fa
DM
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. */
ba7c8e29
DM
229
230static void
231strings_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;
cef35d48 243 print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
ba7c8e29
DM
244 }
245 free (mem);
246 }
247}
248
2470e6fa
DM
249/* Scan all of the sections in FILE, and print the strings
250 in the initialized data section(s).
cef35d48 251
ba7c8e29
DM
252 Return true if successful,
253 false if not (such as if FILE is not an object file). */
254
255static boolean
256strings_object_file (file)
257 char *file;
258{
cef35d48 259 bfd *abfd = bfd_openr (file, target);
ba7c8e29
DM
260
261 if (abfd == NULL)
262 {
cef35d48 263 /* Treat the file as a non-object file. */
ba7c8e29
DM
264 return false;
265 }
266
cef35d48
DM
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 }
ba7c8e29
DM
275
276 got_a_section = false;
277 bfd_map_over_sections (abfd, strings_a_section, file);
278
279 if (!bfd_close (abfd))
280 {
cef35d48 281 bfd_nonfatal (file);
ba7c8e29
DM
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
290static boolean
291strings_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
2470e6fa 310 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
ba7c8e29
DM
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
cef35d48
DM
328 If STREAM is NULL, do not read from it.
329 The caller can supply a buffer of characters
ba7c8e29
DM
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
335static void
2470e6fa 336print_strings (filename, stream, address, stop_point, magiccount, magic)
ba7c8e29
DM
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 {
cef35d48
DM
365 if (stream == NULL)
366 return;
ba7c8e29
DM
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 {
cef35d48
DM
394 if (stream == NULL)
395 return;
ba7c8e29
DM
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:
cef35d48 417 printf ("%7lo ", (unsigned long) (address - i - 1));
ba7c8e29
DM
418 break;
419
420 case 10:
cef35d48 421 printf ("%7ld ", (long) (address - i - 1));
ba7c8e29
DM
422 break;
423
424 case 16:
cef35d48 425 printf ("%7lx ", (unsigned long) (address - i - 1));
ba7c8e29
DM
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
457static int
458integer_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
502static void
2470e6fa 503usage (stream, status)
ba7c8e29 504 FILE *stream;
2470e6fa 505 int status;
ba7c8e29
DM
506{
507 fprintf (stream, "\
2470e6fa 508Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\
ba7c8e29 509 [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
cef35d48 510 [--target=bfdname] [--help] [--version] file...\n",
ba7c8e29 511 program_name);
2470e6fa 512 exit (status);
ba7c8e29 513}
This page took 0.106234 seconds and 4 git commands to generate.