* Many files: Added gettext invocations around user-visible
[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
DM
124
125 program_name = argv[0];
9d04d618 126 xmalloc_set_program_name (program_name);
ba7c8e29
DM
127 string_min = -1;
128 print_addresses = false;
129 print_filenames = false;
130 datasection_only = true;
cef35d48 131 target = NULL;
ba7c8e29 132
2470e6fa 133 while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789",
ba7c8e29
DM
134 long_options, (int *) 0)) != EOF)
135 {
136 switch (optc)
137 {
138 case 'a':
139 datasection_only = false;
140 break;
141
142 case 'f':
143 print_filenames = true;
144 break;
145
146 case 'h':
2470e6fa 147 usage (stdout, 0);
ba7c8e29
DM
148
149 case 'n':
150 string_min = integer_arg (optarg);
151 if (string_min < 1)
152 {
9d04d618 153 fprintf (stderr, _("%s: invalid number %s\n"),
fa021947 154 program_name, optarg);
ba7c8e29
DM
155 exit (1);
156 }
157 break;
158
159 case 'o':
160 print_addresses = true;
161 address_radix = 8;
162 break;
163
164 case 't':
165 print_addresses = true;
166 if (optarg[1] != '\0')
2470e6fa 167 usage (stderr, 1);
ba7c8e29
DM
168 switch (optarg[0])
169 {
170 case 'o':
171 address_radix = 8;
172 break;
173
174 case 'd':
175 address_radix = 10;
176 break;
177
178 case 'x':
179 address_radix = 16;
180 break;
181
182 default:
2470e6fa 183 usage (stderr, 1);
ba7c8e29
DM
184 }
185 break;
186
cef35d48
DM
187 case 'T':
188 target = optarg;
189 break;
190
ba7c8e29 191 case 'v':
9d04d618
TT
192 print_version ("strings");
193 break;
ba7c8e29
DM
194
195 case '?':
2470e6fa 196 usage (stderr, 1);
ba7c8e29
DM
197
198 default:
199 if (string_min < 0)
200 string_min = optc;
201 else
202 string_min = string_min * 10 + optc - '0';
203 break;
204 }
205 }
206
207 if (string_min < 0)
208 string_min = 4;
209
210 bfd_init ();
9d04d618 211 set_default_bfd_target ();
ba7c8e29 212
9d04d618 213 if (optind >= argc)
ba7c8e29 214 {
9d04d618
TT
215 datasection_only = false;
216 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
217 files_given = true;
218 }
219 else
220 {
221 for (; optind < argc; ++optind)
ba7c8e29 222 {
9d04d618
TT
223 if (strcmp (argv[optind], "-") == 0)
224 datasection_only = false;
225 else
226 {
227 files_given = true;
228 exit_status |= (strings_file (argv[optind]) == false);
229 }
ba7c8e29
DM
230 }
231 }
232
233 if (files_given == false)
2470e6fa 234 usage (stderr, 1);
ba7c8e29 235
9d04d618 236 return (exit_status);
ba7c8e29
DM
237}
238\f
2470e6fa
DM
239/* Scan section SECT of the file ABFD, whose printable name is FILE.
240 If it contains initialized data,
241 set `got_a_section' and print the strings in it. */
ba7c8e29
DM
242
243static void
9d04d618 244strings_a_section (abfd, sect, filearg)
ba7c8e29
DM
245 bfd *abfd;
246 asection *sect;
9d04d618 247 PTR filearg;
ba7c8e29 248{
9d04d618
TT
249 const char *file = (const char *) filearg;
250
ba7c8e29
DM
251 if ((sect->flags & DATA_FLAGS) == DATA_FLAGS)
252 {
253 bfd_size_type sz = bfd_get_section_size_before_reloc (sect);
254 PTR mem = xmalloc (sz);
255 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz))
256 {
257 got_a_section = true;
cef35d48 258 print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
ba7c8e29
DM
259 }
260 free (mem);
261 }
262}
263
2470e6fa
DM
264/* Scan all of the sections in FILE, and print the strings
265 in the initialized data section(s).
cef35d48 266
ba7c8e29
DM
267 Return true if successful,
268 false if not (such as if FILE is not an object file). */
269
270static boolean
271strings_object_file (file)
9d04d618 272 const char *file;
ba7c8e29 273{
cef35d48 274 bfd *abfd = bfd_openr (file, target);
ba7c8e29
DM
275
276 if (abfd == NULL)
277 {
cef35d48 278 /* Treat the file as a non-object file. */
ba7c8e29
DM
279 return false;
280 }
281
cef35d48
DM
282 /* This call is mainly for its side effect of reading in the sections.
283 We follow the traditional behavior of `strings' in that we don't
284 complain if we don't recognize a file to be an object file. */
285 if (bfd_check_format (abfd, bfd_object) == false)
286 {
287 bfd_close (abfd);
288 return false;
289 }
ba7c8e29
DM
290
291 got_a_section = false;
9d04d618 292 bfd_map_over_sections (abfd, strings_a_section, (PTR) file);
ba7c8e29
DM
293
294 if (!bfd_close (abfd))
295 {
cef35d48 296 bfd_nonfatal (file);
ba7c8e29
DM
297 return false;
298 }
299
300 return got_a_section;
301}
302
303/* Print the strings in FILE. Return true if ok, false if an error occurs. */
304
305static boolean
306strings_file (file)
307 char *file;
308{
309 /* If we weren't told to scan the whole file,
310 try to open it as an object file and only look at
311 initialized data sections. If that fails, fall back to the
312 whole file. */
313 if (!datasection_only || !strings_object_file (file))
314 {
315 FILE *stream;
316
9d04d618
TT
317 stream = fopen (file, "rb");
318 /* Not all systems permit "rb", so try "r" if it failed. */
319 if (stream == NULL)
320 stream = fopen (file, "r");
ba7c8e29
DM
321 if (stream == NULL)
322 {
323 fprintf (stderr, "%s: ", program_name);
324 perror (file);
325 return false;
326 }
327
2470e6fa 328 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
ba7c8e29
DM
329
330 if (fclose (stream) == EOF)
331 {
332 fprintf (stderr, "%s: ", program_name);
333 perror (file);
334 return false;
335 }
336 }
337
338 return true;
339}
340\f
341/* Find the strings in file FILENAME, read from STREAM.
342 Assume that STREAM is positioned so that the next byte read
343 is at address ADDRESS in the file.
344 Stop reading at address STOP_POINT in the file, if nonzero.
345
cef35d48
DM
346 If STREAM is NULL, do not read from it.
347 The caller can supply a buffer of characters
ba7c8e29
DM
348 to be processed before the data in STREAM.
349 MAGIC is the address of the buffer and
350 MAGICCOUNT is how many characters are in it.
351 Those characters come at address ADDRESS and the data in STREAM follow. */
352
353static void
2470e6fa 354print_strings (filename, stream, address, stop_point, magiccount, magic)
9d04d618 355 const char *filename;
ba7c8e29
DM
356 FILE *stream;
357 file_ptr address;
358 int stop_point;
359 int magiccount;
360 char *magic;
361{
9d04d618 362 char *buf = (char *) xmalloc (string_min + 1);
ba7c8e29
DM
363
364 while (1)
365 {
9d04d618 366 file_ptr start;
ba7c8e29
DM
367 int i;
368 int c;
369
370 /* See if the next `string_min' chars are all graphic chars. */
371 tryline:
372 if (stop_point && address >= stop_point)
373 break;
9d04d618 374 start = address;
ba7c8e29
DM
375 for (i = 0; i < string_min; i++)
376 {
377 if (magiccount)
378 {
379 magiccount--;
380 c = *magic++;
381 }
382 else
383 {
cef35d48
DM
384 if (stream == NULL)
385 return;
ba7c8e29 386 c = getc (stream);
9d04d618 387 if (c == EOF)
ba7c8e29
DM
388 return;
389 }
390 address++;
391 if (!isgraphic (c))
392 /* Found a non-graphic. Try again starting with next char. */
393 goto tryline;
394 buf[i] = c;
395 }
396
9d04d618
TT
397 /* We found a run of `string_min' graphic characters. Print up
398 to the next non-graphic character. */
ba7c8e29 399
ba7c8e29
DM
400 if (print_filenames)
401 printf ("%s: ", filename);
402 if (print_addresses)
403 switch (address_radix)
404 {
405 case 8:
9d04d618 406 printf ("%7lo ", (unsigned long) start);
ba7c8e29
DM
407 break;
408
409 case 10:
9d04d618 410 printf ("%7ld ", (long) start);
ba7c8e29
DM
411 break;
412
413 case 16:
9d04d618 414 printf ("%7lx ", (unsigned long) start);
ba7c8e29
DM
415 break;
416 }
417
9d04d618
TT
418 buf[i] = '\0';
419 fputs (buf, stdout);
420
421 while (1)
422 {
423 if (magiccount)
424 {
425 magiccount--;
426 c = *magic++;
427 }
428 else
429 {
430 if (stream == NULL)
431 break;
432 c = getc (stream);
433 if (c == EOF)
434 break;
435 }
436 address++;
437 if (! isgraphic (c))
ba7c8e29 438 break;
9d04d618
TT
439 putchar (c);
440 }
441
ba7c8e29
DM
442 putchar ('\n');
443 }
444}
445\f
446/* Parse string S as an integer, using decimal radix by default,
447 but allowing octal and hex numbers as in C. */
448
449static int
450integer_arg (s)
451 char *s;
452{
453 int value;
454 int radix = 10;
455 char *p = s;
456 int c;
457
458 if (*p != '0')
459 radix = 10;
460 else if (*++p == 'x')
461 {
462 radix = 16;
463 p++;
464 }
465 else
466 radix = 8;
467
468 value = 0;
469 while (((c = *p++) >= '0' && c <= '9')
470 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
471 {
472 value *= radix;
473 if (c >= '0' && c <= '9')
474 value += c - '0';
475 else
476 value += (c & ~40) - 'A';
477 }
478
479 if (c == 'b')
480 value *= 512;
481 else if (c == 'B')
482 value *= 1024;
483 else
484 p--;
485
486 if (*p)
487 {
9d04d618 488 fprintf (stderr, _("%s: invalid integer argument %s\n"), program_name, s);
ba7c8e29
DM
489 exit (1);
490 }
491 return value;
492}
493
494static void
2470e6fa 495usage (stream, status)
ba7c8e29 496 FILE *stream;
2470e6fa 497 int status;
ba7c8e29 498{
9d04d618 499 fprintf (stream, _("\
2470e6fa 500Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\
ba7c8e29 501 [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
9d04d618 502 [--target=bfdname] [--help] [--version] file...\n"),
ba7c8e29 503 program_name);
9d04d618
TT
504 list_supported_targets (program_name, stream);
505 if (status == 0)
506 fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n"));
2470e6fa 507 exit (status);
ba7c8e29 508}
This page took 0.192675 seconds and 4 git commands to generate.