Locale changes from Bruno Haible <haible@clisp.cons.org>.
[deliverable/binutils-gdb.git] / binutils / strings.c
CommitLineData
252b5132 1/* strings -- print the strings of printable characters in files
d132876a 2 Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
37cc8ec1 3 Free Software Foundation, Inc.
252b5132
RH
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
d132876a
NC
42 --encoding={s,b,l,B,L}
43 -e {s,b,l,B,L}
44 Select character encoding: single-byte, bigendian 16-bit,
45 littleendian 16-bit, bigendian 32-bit, littleendian 32-bit
46
252b5132
RH
47 --target=BFDNAME
48 Specify a non-default object file format.
49
50 --help
51 -h Print the usage message on the standard output.
52
53 --version
54 -v Print the program version number.
55
56 Written by Richard Stallman <rms@gnu.ai.mit.edu>
57 and David MacKenzie <djm@gnu.ai.mit.edu>. */
58
59#include "bfd.h"
60#include <stdio.h>
61#include <getopt.h>
252b5132
RH
62#include <errno.h>
63#include "bucomm.h"
64#include "libiberty.h"
3882b010 65#include "safe-ctype.h"
252b5132 66
5af11cab
AM
67/* Some platforms need to put stdin into binary mode, to read
68 binary files. */
69#ifdef HAVE_SETMODE
70#ifndef O_BINARY
71#ifdef _O_BINARY
72#define O_BINARY _O_BINARY
73#define setmode _setmode
74#else
75#define O_BINARY 0
76#endif
77#endif
78#if O_BINARY
79#include <io.h>
80#define SET_BINARY(f) do { if (!isatty(f)) setmode(f,O_BINARY); } while (0)
81#endif
82#endif
83
3882b010 84#define isgraphic(c) (ISPRINT (c) || (c) == '\t')
252b5132
RH
85
86#ifndef errno
87extern int errno;
88#endif
89
90/* The BFD section flags that identify an initialized data section. */
91#define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
92
93/* Radix for printing addresses (must be 8, 10 or 16). */
94static int address_radix;
95
96/* Minimum length of sequence of graphic chars to trigger output. */
97static int string_min;
98
99/* true means print address within file for each string. */
100static boolean print_addresses;
101
102/* true means print filename for each string. */
103static boolean print_filenames;
104
105/* true means for object files scan only the data section. */
106static boolean datasection_only;
107
108/* true if we found an initialized data section in the current file. */
109static boolean got_a_section;
110
111/* The BFD object file format. */
112static char *target;
113
d132876a
NC
114/* The character encoding format. */
115static char encoding;
116static int encoding_bytes;
117
252b5132
RH
118static struct option long_options[] =
119{
120 {"all", no_argument, NULL, 'a'},
121 {"print-file-name", no_argument, NULL, 'f'},
122 {"bytes", required_argument, NULL, 'n'},
123 {"radix", required_argument, NULL, 't'},
d132876a 124 {"encoding", required_argument, NULL, 'e'},
252b5132
RH
125 {"target", required_argument, NULL, 'T'},
126 {"help", no_argument, NULL, 'h'},
127 {"version", no_argument, NULL, 'v'},
128 {NULL, 0, NULL, 0}
129};
130
131static void strings_a_section PARAMS ((bfd *, asection *, PTR));
132static boolean strings_object_file PARAMS ((const char *));
133static boolean strings_file PARAMS ((char *file));
134static int integer_arg PARAMS ((char *s));
135static void print_strings PARAMS ((const char *filename, FILE *stream,
136 file_ptr address, int stop_point,
137 int magiccount, char *magic));
138static void usage PARAMS ((FILE *stream, int status));
139\f
140int
141main (argc, argv)
142 int argc;
143 char **argv;
144{
145 int optc;
146 int exit_status = 0;
147 boolean files_given = false;
148
3882b010 149#if defined (HAVE_SETLOCALE)
1c529ca6 150 setlocale (LC_ALL, "");
252b5132
RH
151#endif
152 bindtextdomain (PACKAGE, LOCALEDIR);
153 textdomain (PACKAGE);
154
155 program_name = argv[0];
156 xmalloc_set_program_name (program_name);
157 string_min = -1;
158 print_addresses = false;
159 print_filenames = false;
160 datasection_only = true;
161 target = NULL;
d132876a 162 encoding = 's';
252b5132 163
d132876a 164 while ((optc = getopt_long (argc, argv, "afn:ot:e:v0123456789",
252b5132
RH
165 long_options, (int *) 0)) != EOF)
166 {
167 switch (optc)
168 {
169 case 'a':
170 datasection_only = false;
171 break;
172
173 case 'f':
174 print_filenames = true;
175 break;
176
177 case 'h':
178 usage (stdout, 0);
179
180 case 'n':
181 string_min = integer_arg (optarg);
182 if (string_min < 1)
183 {
37cc8ec1 184 fatal (_("invalid number %s"), optarg);
252b5132
RH
185 }
186 break;
187
188 case 'o':
189 print_addresses = true;
190 address_radix = 8;
191 break;
192
193 case 't':
194 print_addresses = true;
195 if (optarg[1] != '\0')
196 usage (stderr, 1);
197 switch (optarg[0])
198 {
199 case 'o':
200 address_radix = 8;
201 break;
202
203 case 'd':
204 address_radix = 10;
205 break;
206
207 case 'x':
208 address_radix = 16;
209 break;
210
211 default:
212 usage (stderr, 1);
213 }
214 break;
215
216 case 'T':
217 target = optarg;
218 break;
219
d132876a
NC
220 case 'e':
221 if (optarg[1] != '\0')
222 usage (stderr, 1);
223 encoding = optarg[0];
224 break;
225
252b5132
RH
226 case 'v':
227 print_version ("strings");
228 break;
229
230 case '?':
231 usage (stderr, 1);
232
233 default:
234 if (string_min < 0)
221f77a9 235 string_min = optc - '0';
252b5132
RH
236 else
237 string_min = string_min * 10 + optc - '0';
238 break;
239 }
240 }
241
242 if (string_min < 0)
243 string_min = 4;
244
d132876a
NC
245 switch (encoding)
246 {
247 case 's':
248 encoding_bytes = 1;
249 break;
250 case 'b':
251 case 'l':
252 encoding_bytes = 2;
253 break;
254 case 'B':
255 case 'L':
256 encoding_bytes = 4;
257 break;
258 default:
259 usage (stderr, 1);
260 }
261
252b5132
RH
262 bfd_init ();
263 set_default_bfd_target ();
264
265 if (optind >= argc)
266 {
267 datasection_only = false;
5af11cab
AM
268#ifdef SET_BINARY
269 SET_BINARY (fileno (stdin));
270#endif
252b5132
RH
271 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
272 files_given = true;
273 }
274 else
275 {
276 for (; optind < argc; ++optind)
277 {
278 if (strcmp (argv[optind], "-") == 0)
279 datasection_only = false;
280 else
281 {
282 files_given = true;
283 exit_status |= (strings_file (argv[optind]) == false);
284 }
285 }
286 }
287
288 if (files_given == false)
289 usage (stderr, 1);
290
291 return (exit_status);
292}
293\f
294/* Scan section SECT of the file ABFD, whose printable name is FILE.
295 If it contains initialized data,
296 set `got_a_section' and print the strings in it. */
297
298static void
299strings_a_section (abfd, sect, filearg)
300 bfd *abfd;
301 asection *sect;
302 PTR filearg;
303{
304 const char *file = (const char *) filearg;
305
306 if ((sect->flags & DATA_FLAGS) == DATA_FLAGS)
307 {
308 bfd_size_type sz = bfd_get_section_size_before_reloc (sect);
309 PTR mem = xmalloc (sz);
310 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz))
311 {
312 got_a_section = true;
313 print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
314 }
315 free (mem);
316 }
317}
318
319/* Scan all of the sections in FILE, and print the strings
320 in the initialized data section(s).
321
322 Return true if successful,
323 false if not (such as if FILE is not an object file). */
324
325static boolean
326strings_object_file (file)
327 const char *file;
328{
329 bfd *abfd = bfd_openr (file, target);
330
331 if (abfd == NULL)
332 {
333 /* Treat the file as a non-object file. */
334 return false;
335 }
336
337 /* This call is mainly for its side effect of reading in the sections.
338 We follow the traditional behavior of `strings' in that we don't
339 complain if we don't recognize a file to be an object file. */
340 if (bfd_check_format (abfd, bfd_object) == false)
341 {
342 bfd_close (abfd);
343 return false;
344 }
345
346 got_a_section = false;
347 bfd_map_over_sections (abfd, strings_a_section, (PTR) file);
348
349 if (!bfd_close (abfd))
350 {
351 bfd_nonfatal (file);
352 return false;
353 }
354
355 return got_a_section;
356}
357
358/* Print the strings in FILE. Return true if ok, false if an error occurs. */
359
360static boolean
361strings_file (file)
362 char *file;
363{
364 /* If we weren't told to scan the whole file,
365 try to open it as an object file and only look at
366 initialized data sections. If that fails, fall back to the
367 whole file. */
368 if (!datasection_only || !strings_object_file (file))
369 {
370 FILE *stream;
371
372 stream = fopen (file, "rb");
373 /* Not all systems permit "rb", so try "r" if it failed. */
374 if (stream == NULL)
375 stream = fopen (file, "r");
376 if (stream == NULL)
377 {
378 fprintf (stderr, "%s: ", program_name);
379 perror (file);
380 return false;
381 }
382
383 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
384
385 if (fclose (stream) == EOF)
386 {
387 fprintf (stderr, "%s: ", program_name);
388 perror (file);
389 return false;
390 }
391 }
392
393 return true;
394}
395\f
d132876a
NC
396/* Read the next character, return EOF if none available.
397 Assume that STREAM is positioned so that the next byte read
398 is at address ADDRESS in the file.
399
400 If STREAM is NULL, do not read from it.
401 The caller can supply a buffer of characters
402 to be processed before the data in STREAM.
403 MAGIC is the address of the buffer and
404 MAGICCOUNT is how many characters are in it. */
405
406static long
407get_char (stream, address, magiccount, magic)
408 FILE *stream;
409 file_ptr *address;
410 int *magiccount;
411 char **magic;
412{
413 int c, i;
414 long r;
415 unsigned char buf[4];
416
417 for (i = 0; i < encoding_bytes; i++)
418 {
419 if (*magiccount)
420 {
421 (*magiccount)--;
422 c = *(*magic)++;
423 }
424 else
425 {
426 if (stream == NULL)
427 return EOF;
428 c = getc (stream);
429 if (c == EOF)
430 return EOF;
431 }
432
433 (*address)++;
434 buf[i] = c;
435 }
436
437 switch (encoding)
438 {
439 case 's':
440 r = buf[0];
441 break;
442 case 'b':
443 r = (buf[0] << 8) | buf[1];
444 break;
445 case 'l':
446 r = buf[0] | (buf[1] << 8);
447 break;
448 case 'B':
449 r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
450 ((long) buf[2] << 8) | buf[3];
451 break;
452 case 'L':
453 r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
454 ((long) buf[3] << 24);
455 break;
456 }
457
458 if (r == EOF)
459 return 0;
460
461 return r;
462}
463\f
252b5132
RH
464/* Find the strings in file FILENAME, read from STREAM.
465 Assume that STREAM is positioned so that the next byte read
466 is at address ADDRESS in the file.
467 Stop reading at address STOP_POINT in the file, if nonzero.
468
469 If STREAM is NULL, do not read from it.
470 The caller can supply a buffer of characters
471 to be processed before the data in STREAM.
472 MAGIC is the address of the buffer and
473 MAGICCOUNT is how many characters are in it.
474 Those characters come at address ADDRESS and the data in STREAM follow. */
475
476static void
477print_strings (filename, stream, address, stop_point, magiccount, magic)
478 const char *filename;
479 FILE *stream;
480 file_ptr address;
481 int stop_point;
482 int magiccount;
483 char *magic;
484{
d132876a 485 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
252b5132
RH
486
487 while (1)
488 {
489 file_ptr start;
490 int i;
d132876a 491 long c;
252b5132
RH
492
493 /* See if the next `string_min' chars are all graphic chars. */
494 tryline:
495 if (stop_point && address >= stop_point)
496 break;
497 start = address;
498 for (i = 0; i < string_min; i++)
499 {
d132876a
NC
500 c = get_char (stream, &address, &magiccount, &magic);
501 if (c == EOF)
502 return;
503 if (c > 255 || c < 0 || !isgraphic (c))
252b5132
RH
504 /* Found a non-graphic. Try again starting with next char. */
505 goto tryline;
506 buf[i] = c;
507 }
508
509 /* We found a run of `string_min' graphic characters. Print up
510 to the next non-graphic character. */
511
512 if (print_filenames)
513 printf ("%s: ", filename);
514 if (print_addresses)
515 switch (address_radix)
516 {
517 case 8:
518 printf ("%7lo ", (unsigned long) start);
519 break;
520
521 case 10:
522 printf ("%7ld ", (long) start);
523 break;
524
525 case 16:
526 printf ("%7lx ", (unsigned long) start);
527 break;
528 }
529
530 buf[i] = '\0';
531 fputs (buf, stdout);
532
533 while (1)
534 {
d132876a
NC
535 c = get_char (stream, &address, &magiccount, &magic);
536 if (c == EOF)
537 break;
538 if (c > 255 || c < 0 || !isgraphic (c))
252b5132
RH
539 break;
540 putchar (c);
541 }
542
543 putchar ('\n');
544 }
545}
546\f
547/* Parse string S as an integer, using decimal radix by default,
548 but allowing octal and hex numbers as in C. */
549
550static int
551integer_arg (s)
552 char *s;
553{
554 int value;
555 int radix = 10;
556 char *p = s;
557 int c;
558
559 if (*p != '0')
560 radix = 10;
561 else if (*++p == 'x')
562 {
563 radix = 16;
564 p++;
565 }
566 else
567 radix = 8;
568
569 value = 0;
570 while (((c = *p++) >= '0' && c <= '9')
571 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
572 {
573 value *= radix;
574 if (c >= '0' && c <= '9')
575 value += c - '0';
576 else
577 value += (c & ~40) - 'A';
578 }
579
580 if (c == 'b')
581 value *= 512;
582 else if (c == 'B')
583 value *= 1024;
584 else
585 p--;
586
587 if (*p)
588 {
37cc8ec1 589 fatal (_("invalid integer argument %s"), s);
252b5132
RH
590 }
591 return value;
592}
593
594static void
595usage (stream, status)
596 FILE *stream;
597 int status;
598{
599 fprintf (stream, _("\
d132876a
NC
600Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-e {s,b,l,B,L}]\n\
601 [-] [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
602 [--target=bfdname] [--encoding {s,b,l,B,L}] [--help] [--version] file...\n"),
252b5132
RH
603 program_name);
604 list_supported_targets (program_name, stream);
605 if (status == 0)
8ad3436c 606 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
252b5132
RH
607 exit (status);
608}
This page took 0.098375 seconds and 4 git commands to generate.