* Converted conditional-trap MIPS opcodes to extra-operand variety also.
[deliverable/binutils-gdb.git] / binutils / strings.c
CommitLineData
ba7c8e29 1/* strings -- print the strings of printable characters in files
9d04d618 2 Copyright (C) 1993, 94, 95, 96, 97, 1998 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
9d04d618
TT
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 02111-1307, USA. */
ba7c8e29
DM
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
cef35d48
DM
41 --target=BFDNAME
42 Specify a non-default object file format.
43
ba7c8e29
DM
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
9d04d618 53#include "bfd.h"
ba7c8e29
DM
54#include <stdio.h>
55#include <getopt.h>
56#include <ctype.h>
57#include <errno.h>
2470e6fa 58#include "bucomm.h"
9d04d618 59#include "libiberty.h"
ba7c8e29
DM
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
68extern int errno;
69#endif
70
71/* The BFD section flags that identify an initialized data section. */
9d04d618 72#define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
ba7c8e29
DM
73
74/* Radix for printing addresses (must be 8, 10 or 16). */
75static int address_radix;
76
77/* Minimum length of sequence of graphic chars to trigger output. */
78static int string_min;
79
80/* true means print address within file for each string. */
81static boolean print_addresses;
82
83/* true means print filename for each string. */
84static boolean print_filenames;
85
86/* true means for object files scan only the data section. */
87static boolean datasection_only;
88
89/* true if we found an initialized data section in the current file. */
90static boolean got_a_section;
91
cef35d48
DM
92/* The BFD object file format. */
93static char *target;
ba7c8e29 94
ba7c8e29
DM
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
9d04d618
TT
107static void strings_a_section PARAMS ((bfd *, asection *, PTR));
108static boolean strings_object_file PARAMS ((const char *));
2470e6fa
DM
109static boolean strings_file PARAMS ((char *file));
110static int integer_arg PARAMS ((char *s));
9d04d618 111static void print_strings PARAMS ((const char *filename, FILE *stream,
2470e6fa
DM
112 file_ptr address, int stop_point,
113 int magiccount, char *magic));
114static void usage PARAMS ((FILE *stream, int status));
ba7c8e29 115\f
9d04d618 116int
ba7c8e29
DM
117main (argc, argv)
118 int argc;
119 char **argv;
120{
121 int optc;
122 int exit_status = 0;
fa021947 123 boolean files_given = false;
ba7c8e29 124
19ac4b08
TT
125 setlocale (LC_MESSAGES, "");
126 bindtextdomain (PACKAGE, LOCALEDIR);
127 textdomain (PACKAGE);
128
ba7c8e29 129 program_name = argv[0];
9d04d618 130 xmalloc_set_program_name (program_name);
ba7c8e29
DM
131 string_min = -1;
132 print_addresses = false;
133 print_filenames = false;
134 datasection_only = true;
cef35d48 135 target = NULL;
ba7c8e29 136
2470e6fa 137 while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789",
ba7c8e29
DM
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':
2470e6fa 151 usage (stdout, 0);
ba7c8e29
DM
152
153 case 'n':
154 string_min = integer_arg (optarg);
155 if (string_min < 1)
156 {
9d04d618 157 fprintf (stderr, _("%s: invalid number %s\n"),
fa021947 158 program_name, optarg);
ba7c8e29
DM
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')
2470e6fa 171 usage (stderr, 1);
ba7c8e29
DM
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:
2470e6fa 187 usage (stderr, 1);
ba7c8e29
DM
188 }
189 break;
190
cef35d48
DM
191 case 'T':
192 target = optarg;
193 break;
194
ba7c8e29 195 case 'v':
9d04d618
TT
196 print_version ("strings");
197 break;
ba7c8e29
DM
198
199 case '?':
2470e6fa 200 usage (stderr, 1);
ba7c8e29
DM
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 ();
9d04d618 215 set_default_bfd_target ();
ba7c8e29 216
9d04d618 217 if (optind >= argc)
ba7c8e29 218 {
9d04d618
TT
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)
ba7c8e29 226 {
9d04d618
TT
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 }
ba7c8e29
DM
234 }
235 }
236
237 if (files_given == false)
2470e6fa 238 usage (stderr, 1);
ba7c8e29 239
9d04d618 240 return (exit_status);
ba7c8e29
DM
241}
242\f
2470e6fa
DM
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. */
ba7c8e29
DM
246
247static void
9d04d618 248strings_a_section (abfd, sect, filearg)
ba7c8e29
DM
249 bfd *abfd;
250 asection *sect;
9d04d618 251 PTR filearg;
ba7c8e29 252{
9d04d618
TT
253 const char *file = (const char *) filearg;
254
ba7c8e29
DM
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;
cef35d48 262 print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
ba7c8e29
DM
263 }
264 free (mem);
265 }
266}
267
2470e6fa
DM
268/* Scan all of the sections in FILE, and print the strings
269 in the initialized data section(s).
cef35d48 270
ba7c8e29
DM
271 Return true if successful,
272 false if not (such as if FILE is not an object file). */
273
274static boolean
275strings_object_file (file)
9d04d618 276 const char *file;
ba7c8e29 277{
cef35d48 278 bfd *abfd = bfd_openr (file, target);
ba7c8e29
DM
279
280 if (abfd == NULL)
281 {
cef35d48 282 /* Treat the file as a non-object file. */
ba7c8e29
DM
283 return false;
284 }
285
cef35d48
DM
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 }
ba7c8e29
DM
294
295 got_a_section = false;
9d04d618 296 bfd_map_over_sections (abfd, strings_a_section, (PTR) file);
ba7c8e29
DM
297
298 if (!bfd_close (abfd))
299 {
cef35d48 300 bfd_nonfatal (file);
ba7c8e29
DM
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
309static boolean
310strings_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
9d04d618
TT
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");
ba7c8e29
DM
325 if (stream == NULL)
326 {
327 fprintf (stderr, "%s: ", program_name);
328 perror (file);
329 return false;
330 }
331
2470e6fa 332 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
ba7c8e29
DM
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
cef35d48
DM
350 If STREAM is NULL, do not read from it.
351 The caller can supply a buffer of characters
ba7c8e29
DM
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
357static void
2470e6fa 358print_strings (filename, stream, address, stop_point, magiccount, magic)
9d04d618 359 const char *filename;
ba7c8e29
DM
360 FILE *stream;
361 file_ptr address;
362 int stop_point;
363 int magiccount;
364 char *magic;
365{
9d04d618 366 char *buf = (char *) xmalloc (string_min + 1);
ba7c8e29
DM
367
368 while (1)
369 {
9d04d618 370 file_ptr start;
ba7c8e29
DM
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;
9d04d618 378 start = address;
ba7c8e29
DM
379 for (i = 0; i < string_min; i++)
380 {
381 if (magiccount)
382 {
383 magiccount--;
384 c = *magic++;
385 }
386 else
387 {
cef35d48
DM
388 if (stream == NULL)
389 return;
ba7c8e29 390 c = getc (stream);
9d04d618 391 if (c == EOF)
ba7c8e29
DM
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
9d04d618
TT
401 /* We found a run of `string_min' graphic characters. Print up
402 to the next non-graphic character. */
ba7c8e29 403
ba7c8e29
DM
404 if (print_filenames)
405 printf ("%s: ", filename);
406 if (print_addresses)
407 switch (address_radix)
408 {
409 case 8:
9d04d618 410 printf ("%7lo ", (unsigned long) start);
ba7c8e29
DM
411 break;
412
413 case 10:
9d04d618 414 printf ("%7ld ", (long) start);
ba7c8e29
DM
415 break;
416
417 case 16:
9d04d618 418 printf ("%7lx ", (unsigned long) start);
ba7c8e29
DM
419 break;
420 }
421
9d04d618
TT
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))
ba7c8e29 442 break;
9d04d618
TT
443 putchar (c);
444 }
445
ba7c8e29
DM
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
453static int
454integer_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 {
9d04d618 492 fprintf (stderr, _("%s: invalid integer argument %s\n"), program_name, s);
ba7c8e29
DM
493 exit (1);
494 }
495 return value;
496}
497
498static void
2470e6fa 499usage (stream, status)
ba7c8e29 500 FILE *stream;
2470e6fa 501 int status;
ba7c8e29 502{
9d04d618 503 fprintf (stream, _("\
2470e6fa 504Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\
ba7c8e29 505 [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
9d04d618 506 [--target=bfdname] [--help] [--version] file...\n"),
ba7c8e29 507 program_name);
9d04d618
TT
508 list_supported_targets (program_name, stream);
509 if (status == 0)
510 fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
2470e6fa 511 exit (status);
ba7c8e29 512}
This page took 0.235338 seconds and 4 git commands to generate.