DataDirectory virtual address is relative. Fix to suit.
[binutils.git] / binutils / strings.c
blobab845b04d42bc9a3313a55ac91c225bc4df39b00
1 /* strings -- print the strings of printable characters in files
2 Copyright (C) 1993, 94, 95, 96, 97, 98, 99, 2000
3 Free Software Foundation, Inc.
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.
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.
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. */
20 /* Usage: strings [options] file...
22 Options:
23 --all
25 - Do not scan only the initialized data section of object files.
27 --print-file-name
28 -f Print the name of the file before each string.
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.
35 --radix={o,x,d}
36 -t {o,x,d} Print the offset within the file before each string,
37 in octal/hex/decimal.
39 -o Like -to. (Some other implementations have -o like -to,
40 others like -td. We chose one arbitrarily.)
42 --target=BFDNAME
43 Specify a non-default object file format.
45 --help
46 -h Print the usage message on the standard output.
48 --version
49 -v Print the program version number.
51 Written by Richard Stallman <rms@gnu.ai.mit.edu>
52 and David MacKenzie <djm@gnu.ai.mit.edu>. */
54 #include "bfd.h"
55 #include <stdio.h>
56 #include <getopt.h>
57 #include <ctype.h>
58 #include <errno.h>
59 #include "bucomm.h"
60 #include "libiberty.h"
62 #ifdef isascii
63 #define isgraphic(c) (isascii (c) && isprint (c))
64 #else
65 #define isgraphic(c) (isprint (c))
66 #endif
68 #ifndef errno
69 extern int errno;
70 #endif
72 /* The BFD section flags that identify an initialized data section. */
73 #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
75 /* Radix for printing addresses (must be 8, 10 or 16). */
76 static int address_radix;
78 /* Minimum length of sequence of graphic chars to trigger output. */
79 static int string_min;
81 /* true means print address within file for each string. */
82 static boolean print_addresses;
84 /* true means print filename for each string. */
85 static boolean print_filenames;
87 /* true means for object files scan only the data section. */
88 static boolean datasection_only;
90 /* true if we found an initialized data section in the current file. */
91 static boolean got_a_section;
93 /* The BFD object file format. */
94 static char *target;
96 static struct option long_options[] =
98 {"all", no_argument, NULL, 'a'},
99 {"print-file-name", no_argument, NULL, 'f'},
100 {"bytes", required_argument, NULL, 'n'},
101 {"radix", required_argument, NULL, 't'},
102 {"target", required_argument, NULL, 'T'},
103 {"help", no_argument, NULL, 'h'},
104 {"version", no_argument, NULL, 'v'},
105 {NULL, 0, NULL, 0}
108 static void strings_a_section PARAMS ((bfd *, asection *, PTR));
109 static boolean strings_object_file PARAMS ((const char *));
110 static boolean strings_file PARAMS ((char *file));
111 static int integer_arg PARAMS ((char *s));
112 static void print_strings PARAMS ((const char *filename, FILE *stream,
113 file_ptr address, int stop_point,
114 int magiccount, char *magic));
115 static void usage PARAMS ((FILE *stream, int status));
118 main (argc, argv)
119 int argc;
120 char **argv;
122 int optc;
123 int exit_status = 0;
124 boolean files_given = false;
126 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
127 setlocale (LC_MESSAGES, "");
128 #endif
129 bindtextdomain (PACKAGE, LOCALEDIR);
130 textdomain (PACKAGE);
132 program_name = argv[0];
133 xmalloc_set_program_name (program_name);
134 string_min = -1;
135 print_addresses = false;
136 print_filenames = false;
137 datasection_only = true;
138 target = NULL;
140 while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789",
141 long_options, (int *) 0)) != EOF)
143 switch (optc)
145 case 'a':
146 datasection_only = false;
147 break;
149 case 'f':
150 print_filenames = true;
151 break;
153 case 'h':
154 usage (stdout, 0);
156 case 'n':
157 string_min = integer_arg (optarg);
158 if (string_min < 1)
160 fatal (_("invalid number %s"), optarg);
162 break;
164 case 'o':
165 print_addresses = true;
166 address_radix = 8;
167 break;
169 case 't':
170 print_addresses = true;
171 if (optarg[1] != '\0')
172 usage (stderr, 1);
173 switch (optarg[0])
175 case 'o':
176 address_radix = 8;
177 break;
179 case 'd':
180 address_radix = 10;
181 break;
183 case 'x':
184 address_radix = 16;
185 break;
187 default:
188 usage (stderr, 1);
190 break;
192 case 'T':
193 target = optarg;
194 break;
196 case 'v':
197 print_version ("strings");
198 break;
200 case '?':
201 usage (stderr, 1);
203 default:
204 if (string_min < 0)
205 string_min = optc - '0';
206 else
207 string_min = string_min * 10 + optc - '0';
208 break;
212 if (string_min < 0)
213 string_min = 4;
215 bfd_init ();
216 set_default_bfd_target ();
218 if (optind >= argc)
220 datasection_only = false;
221 print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
222 files_given = true;
224 else
226 for (; optind < argc; ++optind)
228 if (strcmp (argv[optind], "-") == 0)
229 datasection_only = false;
230 else
232 files_given = true;
233 exit_status |= (strings_file (argv[optind]) == false);
238 if (files_given == false)
239 usage (stderr, 1);
241 return (exit_status);
244 /* Scan section SECT of the file ABFD, whose printable name is FILE.
245 If it contains initialized data,
246 set `got_a_section' and print the strings in it. */
248 static void
249 strings_a_section (abfd, sect, filearg)
250 bfd *abfd;
251 asection *sect;
252 PTR filearg;
254 const char *file = (const char *) filearg;
256 if ((sect->flags & DATA_FLAGS) == DATA_FLAGS)
258 bfd_size_type sz = bfd_get_section_size_before_reloc (sect);
259 PTR mem = xmalloc (sz);
260 if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz))
262 got_a_section = true;
263 print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem);
265 free (mem);
269 /* Scan all of the sections in FILE, and print the strings
270 in the initialized data section(s).
272 Return true if successful,
273 false if not (such as if FILE is not an object file). */
275 static boolean
276 strings_object_file (file)
277 const char *file;
279 bfd *abfd = bfd_openr (file, target);
281 if (abfd == NULL)
283 /* Treat the file as a non-object file. */
284 return false;
287 /* This call is mainly for its side effect of reading in the sections.
288 We follow the traditional behavior of `strings' in that we don't
289 complain if we don't recognize a file to be an object file. */
290 if (bfd_check_format (abfd, bfd_object) == false)
292 bfd_close (abfd);
293 return false;
296 got_a_section = false;
297 bfd_map_over_sections (abfd, strings_a_section, (PTR) file);
299 if (!bfd_close (abfd))
301 bfd_nonfatal (file);
302 return false;
305 return got_a_section;
308 /* Print the strings in FILE. Return true if ok, false if an error occurs. */
310 static boolean
311 strings_file (file)
312 char *file;
314 /* If we weren't told to scan the whole file,
315 try to open it as an object file and only look at
316 initialized data sections. If that fails, fall back to the
317 whole file. */
318 if (!datasection_only || !strings_object_file (file))
320 FILE *stream;
322 stream = fopen (file, "rb");
323 /* Not all systems permit "rb", so try "r" if it failed. */
324 if (stream == NULL)
325 stream = fopen (file, "r");
326 if (stream == NULL)
328 fprintf (stderr, "%s: ", program_name);
329 perror (file);
330 return false;
333 print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
335 if (fclose (stream) == EOF)
337 fprintf (stderr, "%s: ", program_name);
338 perror (file);
339 return false;
343 return true;
346 /* Find the strings in file FILENAME, read from STREAM.
347 Assume that STREAM is positioned so that the next byte read
348 is at address ADDRESS in the file.
349 Stop reading at address STOP_POINT in the file, if nonzero.
351 If STREAM is NULL, do not read from it.
352 The caller can supply a buffer of characters
353 to be processed before the data in STREAM.
354 MAGIC is the address of the buffer and
355 MAGICCOUNT is how many characters are in it.
356 Those characters come at address ADDRESS and the data in STREAM follow. */
358 static void
359 print_strings (filename, stream, address, stop_point, magiccount, magic)
360 const char *filename;
361 FILE *stream;
362 file_ptr address;
363 int stop_point;
364 int magiccount;
365 char *magic;
367 char *buf = (char *) xmalloc (string_min + 1);
369 while (1)
371 file_ptr start;
372 int i;
373 int c;
375 /* See if the next `string_min' chars are all graphic chars. */
376 tryline:
377 if (stop_point && address >= stop_point)
378 break;
379 start = address;
380 for (i = 0; i < string_min; i++)
382 if (magiccount)
384 magiccount--;
385 c = *magic++;
387 else
389 if (stream == NULL)
390 return;
391 c = getc (stream);
392 if (c == EOF)
393 return;
395 address++;
396 if (!isgraphic (c))
397 /* Found a non-graphic. Try again starting with next char. */
398 goto tryline;
399 buf[i] = c;
402 /* We found a run of `string_min' graphic characters. Print up
403 to the next non-graphic character. */
405 if (print_filenames)
406 printf ("%s: ", filename);
407 if (print_addresses)
408 switch (address_radix)
410 case 8:
411 printf ("%7lo ", (unsigned long) start);
412 break;
414 case 10:
415 printf ("%7ld ", (long) start);
416 break;
418 case 16:
419 printf ("%7lx ", (unsigned long) start);
420 break;
423 buf[i] = '\0';
424 fputs (buf, stdout);
426 while (1)
428 if (magiccount)
430 magiccount--;
431 c = *magic++;
433 else
435 if (stream == NULL)
436 break;
437 c = getc (stream);
438 if (c == EOF)
439 break;
441 address++;
442 if (! isgraphic (c))
443 break;
444 putchar (c);
447 putchar ('\n');
451 /* Parse string S as an integer, using decimal radix by default,
452 but allowing octal and hex numbers as in C. */
454 static int
455 integer_arg (s)
456 char *s;
458 int value;
459 int radix = 10;
460 char *p = s;
461 int c;
463 if (*p != '0')
464 radix = 10;
465 else if (*++p == 'x')
467 radix = 16;
468 p++;
470 else
471 radix = 8;
473 value = 0;
474 while (((c = *p++) >= '0' && c <= '9')
475 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
477 value *= radix;
478 if (c >= '0' && c <= '9')
479 value += c - '0';
480 else
481 value += (c & ~40) - 'A';
484 if (c == 'b')
485 value *= 512;
486 else if (c == 'B')
487 value *= 1024;
488 else
489 p--;
491 if (*p)
493 fatal (_("invalid integer argument %s"), s);
495 return value;
498 static void
499 usage (stream, status)
500 FILE *stream;
501 int status;
503 fprintf (stream, _("\
504 Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\
505 [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\
506 [--target=bfdname] [--help] [--version] file...\n"),
507 program_name);
508 list_supported_targets (program_name, stream);
509 if (status == 0)
510 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
511 exit (status);