13d8817e4Smiod /* strings -- print the strings of printable characters in files
23d8817e4Smiod Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
33d8817e4Smiod 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
43d8817e4Smiod
53d8817e4Smiod This program is free software; you can redistribute it and/or modify
63d8817e4Smiod it under the terms of the GNU General Public License as published by
73d8817e4Smiod the Free Software Foundation; either version 2, or (at your option)
83d8817e4Smiod any later version.
93d8817e4Smiod
103d8817e4Smiod This program is distributed in the hope that it will be useful,
113d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
123d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
133d8817e4Smiod GNU General Public License for more details.
143d8817e4Smiod
153d8817e4Smiod You should have received a copy of the GNU General Public License
163d8817e4Smiod along with this program; if not, write to the Free Software
173d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
183d8817e4Smiod 02110-1301, USA. */
193d8817e4Smiod
203d8817e4Smiod /* Usage: strings [options] file...
213d8817e4Smiod
223d8817e4Smiod Options:
233d8817e4Smiod --all
243d8817e4Smiod -a
253d8817e4Smiod - Do not scan only the initialized data section of object files.
263d8817e4Smiod
273d8817e4Smiod --print-file-name
283d8817e4Smiod -f Print the name of the file before each string.
293d8817e4Smiod
303d8817e4Smiod --bytes=min-len
313d8817e4Smiod -n min-len
323d8817e4Smiod -min-len Print graphic char sequences, MIN-LEN or more bytes long,
333d8817e4Smiod that are followed by a NUL or a newline. Default is 4.
343d8817e4Smiod
353d8817e4Smiod --radix={o,x,d}
363d8817e4Smiod -t {o,x,d} Print the offset within the file before each string,
373d8817e4Smiod in octal/hex/decimal.
383d8817e4Smiod
393d8817e4Smiod -o Like -to. (Some other implementations have -o like -to,
403d8817e4Smiod others like -td. We chose one arbitrarily.)
413d8817e4Smiod
423d8817e4Smiod --encoding={s,S,b,l,B,L}
433d8817e4Smiod -e {s,S,b,l,B,L}
443d8817e4Smiod Select character encoding: 7-bit-character, 8-bit-character,
453d8817e4Smiod bigendian 16-bit, littleendian 16-bit, bigendian 32-bit,
463d8817e4Smiod littleendian 32-bit.
473d8817e4Smiod
483d8817e4Smiod --target=BFDNAME
493d8817e4Smiod Specify a non-default object file format.
503d8817e4Smiod
513d8817e4Smiod --help
523d8817e4Smiod -h Print the usage message on the standard output.
533d8817e4Smiod
543d8817e4Smiod --version
553d8817e4Smiod -v Print the program version number.
563d8817e4Smiod
573d8817e4Smiod Written by Richard Stallman <rms@gnu.ai.mit.edu>
583d8817e4Smiod and David MacKenzie <djm@gnu.ai.mit.edu>. */
593d8817e4Smiod
603d8817e4Smiod #ifdef HAVE_CONFIG_H
613d8817e4Smiod #include "config.h"
623d8817e4Smiod #endif
633d8817e4Smiod #include "bfd.h"
643d8817e4Smiod #include <stdio.h>
653d8817e4Smiod #include "getopt.h"
663d8817e4Smiod #include <errno.h>
673d8817e4Smiod #include "bucomm.h"
683d8817e4Smiod #include "libiberty.h"
693d8817e4Smiod #include "safe-ctype.h"
703d8817e4Smiod #include <sys/stat.h>
713d8817e4Smiod
723d8817e4Smiod /* Some platforms need to put stdin into binary mode, to read
733d8817e4Smiod binary files. */
743d8817e4Smiod #ifdef HAVE_SETMODE
753d8817e4Smiod #ifndef O_BINARY
763d8817e4Smiod #ifdef _O_BINARY
773d8817e4Smiod #define O_BINARY _O_BINARY
783d8817e4Smiod #define setmode _setmode
793d8817e4Smiod #else
803d8817e4Smiod #define O_BINARY 0
813d8817e4Smiod #endif
823d8817e4Smiod #endif
833d8817e4Smiod #if O_BINARY
843d8817e4Smiod #include <io.h>
853d8817e4Smiod #define SET_BINARY(f) do { if (!isatty (f)) setmode (f,O_BINARY); } while (0)
863d8817e4Smiod #endif
873d8817e4Smiod #endif
883d8817e4Smiod
893d8817e4Smiod #define STRING_ISGRAPHIC(c) \
903d8817e4Smiod ( (c) >= 0 \
913d8817e4Smiod && (c) <= 255 \
923d8817e4Smiod && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
933d8817e4Smiod
943d8817e4Smiod #ifndef errno
953d8817e4Smiod extern int errno;
963d8817e4Smiod #endif
973d8817e4Smiod
983d8817e4Smiod /* The BFD section flags that identify an initialized data section. */
993d8817e4Smiod #define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
1003d8817e4Smiod
1013d8817e4Smiod #ifdef HAVE_FOPEN64
1023d8817e4Smiod typedef off64_t file_off;
1033d8817e4Smiod #define file_open(s,m) fopen64(s, m)
1043d8817e4Smiod #else
1053d8817e4Smiod typedef off_t file_off;
1063d8817e4Smiod #define file_open(s,m) fopen(s, m)
1073d8817e4Smiod #endif
1083d8817e4Smiod #ifdef HAVE_STAT64
1093d8817e4Smiod typedef struct stat64 statbuf;
1103d8817e4Smiod #define file_stat(f,s) stat64(f, s)
1113d8817e4Smiod #else
1123d8817e4Smiod typedef struct stat statbuf;
1133d8817e4Smiod #define file_stat(f,s) stat(f, s)
1143d8817e4Smiod #endif
1153d8817e4Smiod
1163d8817e4Smiod /* Radix for printing addresses (must be 8, 10 or 16). */
1173d8817e4Smiod static int address_radix;
1183d8817e4Smiod
1193d8817e4Smiod /* Minimum length of sequence of graphic chars to trigger output. */
1203d8817e4Smiod static int string_min;
1213d8817e4Smiod
1223d8817e4Smiod /* TRUE means print address within file for each string. */
1233d8817e4Smiod static bfd_boolean print_addresses;
1243d8817e4Smiod
1253d8817e4Smiod /* TRUE means print filename for each string. */
1263d8817e4Smiod static bfd_boolean print_filenames;
1273d8817e4Smiod
1283d8817e4Smiod /* TRUE means for object files scan only the data section. */
1293d8817e4Smiod static bfd_boolean datasection_only;
1303d8817e4Smiod
1313d8817e4Smiod /* TRUE if we found an initialized data section in the current file. */
1323d8817e4Smiod static bfd_boolean got_a_section;
1333d8817e4Smiod
1343d8817e4Smiod /* The BFD object file format. */
1353d8817e4Smiod static char *target;
1363d8817e4Smiod
1373d8817e4Smiod /* The character encoding format. */
1383d8817e4Smiod static char encoding;
1393d8817e4Smiod static int encoding_bytes;
1403d8817e4Smiod
1413d8817e4Smiod static struct option long_options[] =
1423d8817e4Smiod {
1433d8817e4Smiod {"all", no_argument, NULL, 'a'},
1443d8817e4Smiod {"print-file-name", no_argument, NULL, 'f'},
1453d8817e4Smiod {"bytes", required_argument, NULL, 'n'},
1463d8817e4Smiod {"radix", required_argument, NULL, 't'},
1473d8817e4Smiod {"encoding", required_argument, NULL, 'e'},
1483d8817e4Smiod {"target", required_argument, NULL, 'T'},
1493d8817e4Smiod {"help", no_argument, NULL, 'h'},
1503d8817e4Smiod {"version", no_argument, NULL, 'v'},
1513d8817e4Smiod {NULL, 0, NULL, 0}
1523d8817e4Smiod };
1533d8817e4Smiod
1543d8817e4Smiod /* Records the size of a named file so that we
1553d8817e4Smiod do not repeatedly run bfd_stat() on it. */
1563d8817e4Smiod
1573d8817e4Smiod typedef struct
1583d8817e4Smiod {
1593d8817e4Smiod const char * filename;
1603d8817e4Smiod bfd_size_type filesize;
1613d8817e4Smiod } filename_and_size_t;
1623d8817e4Smiod
1633d8817e4Smiod static void strings_a_section (bfd *, asection *, void *);
1643d8817e4Smiod static bfd_boolean strings_object_file (const char *);
1653d8817e4Smiod static bfd_boolean strings_file (char *file);
1663d8817e4Smiod static int integer_arg (char *s);
1673d8817e4Smiod static void print_strings (const char *, FILE *, file_off, int, int, char *);
1683d8817e4Smiod static void usage (FILE *, int);
1693d8817e4Smiod static long get_char (FILE *, file_off *, int *, char **);
1703d8817e4Smiod
1713d8817e4Smiod int main (int, char **);
1723d8817e4Smiod
1733d8817e4Smiod int
main(int argc,char ** argv)1743d8817e4Smiod main (int argc, char **argv)
1753d8817e4Smiod {
1763d8817e4Smiod int optc;
1773d8817e4Smiod int exit_status = 0;
1783d8817e4Smiod bfd_boolean files_given = FALSE;
1793d8817e4Smiod
1803d8817e4Smiod #if defined (HAVE_SETLOCALE)
1813d8817e4Smiod setlocale (LC_ALL, "");
1823d8817e4Smiod #endif
1833d8817e4Smiod bindtextdomain (PACKAGE, LOCALEDIR);
1843d8817e4Smiod textdomain (PACKAGE);
1853d8817e4Smiod
186c1f838d9Spascal if (pledge ("stdio rpath", NULL) == -1)
187c1f838d9Spascal fatal (_("Failed to pledge"));
188c1f838d9Spascal
1893d8817e4Smiod program_name = argv[0];
1903d8817e4Smiod xmalloc_set_program_name (program_name);
1913d8817e4Smiod
1923d8817e4Smiod expandargv (&argc, &argv);
1933d8817e4Smiod
1943d8817e4Smiod string_min = -1;
1953d8817e4Smiod print_addresses = FALSE;
1963d8817e4Smiod print_filenames = FALSE;
1973d8817e4Smiod datasection_only = TRUE;
1983d8817e4Smiod target = NULL;
1993d8817e4Smiod encoding = 's';
2003d8817e4Smiod
2013d8817e4Smiod while ((optc = getopt_long (argc, argv, "afhHn:ot:e:Vv0123456789",
2023d8817e4Smiod long_options, (int *) 0)) != EOF)
2033d8817e4Smiod {
2043d8817e4Smiod switch (optc)
2053d8817e4Smiod {
2063d8817e4Smiod case 'a':
2073d8817e4Smiod datasection_only = FALSE;
2083d8817e4Smiod break;
2093d8817e4Smiod
2103d8817e4Smiod case 'f':
2113d8817e4Smiod print_filenames = TRUE;
2123d8817e4Smiod break;
2133d8817e4Smiod
2143d8817e4Smiod case 'H':
2153d8817e4Smiod case 'h':
2163d8817e4Smiod usage (stdout, 0);
2173d8817e4Smiod
2183d8817e4Smiod case 'n':
2193d8817e4Smiod string_min = integer_arg (optarg);
2203d8817e4Smiod if (string_min < 1)
2213d8817e4Smiod fatal (_("invalid number %s"), optarg);
2223d8817e4Smiod break;
2233d8817e4Smiod
2243d8817e4Smiod case 'o':
2253d8817e4Smiod print_addresses = TRUE;
2263d8817e4Smiod address_radix = 8;
2273d8817e4Smiod break;
2283d8817e4Smiod
2293d8817e4Smiod case 't':
2303d8817e4Smiod print_addresses = TRUE;
2313d8817e4Smiod if (optarg[1] != '\0')
2323d8817e4Smiod usage (stderr, 1);
2333d8817e4Smiod switch (optarg[0])
2343d8817e4Smiod {
2353d8817e4Smiod case 'o':
2363d8817e4Smiod address_radix = 8;
2373d8817e4Smiod break;
2383d8817e4Smiod
2393d8817e4Smiod case 'd':
2403d8817e4Smiod address_radix = 10;
2413d8817e4Smiod break;
2423d8817e4Smiod
2433d8817e4Smiod case 'x':
2443d8817e4Smiod address_radix = 16;
2453d8817e4Smiod break;
2463d8817e4Smiod
2473d8817e4Smiod default:
2483d8817e4Smiod usage (stderr, 1);
2493d8817e4Smiod }
2503d8817e4Smiod break;
2513d8817e4Smiod
2523d8817e4Smiod case 'T':
2533d8817e4Smiod target = optarg;
2543d8817e4Smiod break;
2553d8817e4Smiod
2563d8817e4Smiod case 'e':
2573d8817e4Smiod if (optarg[1] != '\0')
2583d8817e4Smiod usage (stderr, 1);
2593d8817e4Smiod encoding = optarg[0];
2603d8817e4Smiod break;
2613d8817e4Smiod
2623d8817e4Smiod case 'V':
2633d8817e4Smiod case 'v':
2643d8817e4Smiod print_version ("strings");
2653d8817e4Smiod break;
2663d8817e4Smiod
2673d8817e4Smiod case '?':
2683d8817e4Smiod usage (stderr, 1);
2693d8817e4Smiod
2703d8817e4Smiod default:
2713d8817e4Smiod if (string_min < 0)
2723d8817e4Smiod string_min = optc - '0';
2733d8817e4Smiod else
2743d8817e4Smiod string_min = string_min * 10 + optc - '0';
2753d8817e4Smiod break;
2763d8817e4Smiod }
2773d8817e4Smiod }
2783d8817e4Smiod
2793d8817e4Smiod if (string_min < 0)
2803d8817e4Smiod string_min = 4;
2813d8817e4Smiod
2823d8817e4Smiod switch (encoding)
2833d8817e4Smiod {
2843d8817e4Smiod case 'S':
2853d8817e4Smiod case 's':
2863d8817e4Smiod encoding_bytes = 1;
2873d8817e4Smiod break;
2883d8817e4Smiod case 'b':
2893d8817e4Smiod case 'l':
2903d8817e4Smiod encoding_bytes = 2;
2913d8817e4Smiod break;
2923d8817e4Smiod case 'B':
2933d8817e4Smiod case 'L':
2943d8817e4Smiod encoding_bytes = 4;
2953d8817e4Smiod break;
2963d8817e4Smiod default:
2973d8817e4Smiod usage (stderr, 1);
2983d8817e4Smiod }
2993d8817e4Smiod
3003d8817e4Smiod bfd_init ();
3013d8817e4Smiod set_default_bfd_target ();
3023d8817e4Smiod
3033d8817e4Smiod if (optind >= argc)
3043d8817e4Smiod {
3053d8817e4Smiod datasection_only = FALSE;
3063d8817e4Smiod #ifdef SET_BINARY
3073d8817e4Smiod SET_BINARY (fileno (stdin));
3083d8817e4Smiod #endif
3093d8817e4Smiod print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
3103d8817e4Smiod files_given = TRUE;
3113d8817e4Smiod }
3123d8817e4Smiod else
3133d8817e4Smiod {
3143d8817e4Smiod for (; optind < argc; ++optind)
3153d8817e4Smiod {
3163d8817e4Smiod if (strcmp (argv[optind], "-") == 0)
3173d8817e4Smiod datasection_only = FALSE;
3183d8817e4Smiod else
3193d8817e4Smiod {
3203d8817e4Smiod files_given = TRUE;
3213d8817e4Smiod exit_status |= strings_file (argv[optind]) == FALSE;
3223d8817e4Smiod }
3233d8817e4Smiod }
3243d8817e4Smiod }
3253d8817e4Smiod
3263d8817e4Smiod if (!files_given)
3273d8817e4Smiod usage (stderr, 1);
3283d8817e4Smiod
3293d8817e4Smiod return (exit_status);
3303d8817e4Smiod }
3313d8817e4Smiod
3323d8817e4Smiod /* Scan section SECT of the file ABFD, whose printable name is in
3333d8817e4Smiod ARG->filename and whose size might be in ARG->filesize. If it
3343d8817e4Smiod contains initialized data set `got_a_section' and print the
3353d8817e4Smiod strings in it.
3363d8817e4Smiod
3373d8817e4Smiod FIXME: We ought to be able to return error codes/messages for
3383d8817e4Smiod certain conditions. */
3393d8817e4Smiod
3403d8817e4Smiod static void
strings_a_section(bfd * abfd,asection * sect,void * arg)3413d8817e4Smiod strings_a_section (bfd *abfd, asection *sect, void *arg)
3423d8817e4Smiod {
3433d8817e4Smiod filename_and_size_t * filename_and_sizep;
3443d8817e4Smiod bfd_size_type *filesizep;
3453d8817e4Smiod bfd_size_type sectsize;
3463d8817e4Smiod void *mem;
3473d8817e4Smiod
3483d8817e4Smiod if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
3493d8817e4Smiod return;
3503d8817e4Smiod
3513d8817e4Smiod sectsize = bfd_get_section_size (sect);
3523d8817e4Smiod
3533d8817e4Smiod if (sectsize <= 0)
3543d8817e4Smiod return;
3553d8817e4Smiod
3563d8817e4Smiod /* Get the size of the file. This might have been cached for us. */
3573d8817e4Smiod filename_and_sizep = (filename_and_size_t *) arg;
3583d8817e4Smiod filesizep = & filename_and_sizep->filesize;
3593d8817e4Smiod
3603d8817e4Smiod if (*filesizep == 0)
3613d8817e4Smiod {
3623d8817e4Smiod struct stat st;
3633d8817e4Smiod
3643d8817e4Smiod if (bfd_stat (abfd, &st))
3653d8817e4Smiod return;
3663d8817e4Smiod
3673d8817e4Smiod /* Cache the result so that we do not repeatedly stat this file. */
3683d8817e4Smiod *filesizep = st.st_size;
3693d8817e4Smiod }
3703d8817e4Smiod
3713d8817e4Smiod /* Compare the size of the section against the size of the file.
3723d8817e4Smiod If the section is bigger then the file must be corrupt and
3733d8817e4Smiod we should not try dumping it. */
3743d8817e4Smiod if (sectsize >= *filesizep)
3753d8817e4Smiod return;
3763d8817e4Smiod
3773d8817e4Smiod mem = xmalloc (sectsize);
3783d8817e4Smiod
3793d8817e4Smiod if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
3803d8817e4Smiod {
3813d8817e4Smiod got_a_section = TRUE;
3823d8817e4Smiod
3833d8817e4Smiod print_strings (filename_and_sizep->filename, NULL, sect->filepos,
3843d8817e4Smiod 0, sectsize, mem);
3853d8817e4Smiod }
3863d8817e4Smiod
3873d8817e4Smiod free (mem);
3883d8817e4Smiod }
3893d8817e4Smiod
3903d8817e4Smiod /* Scan all of the sections in FILE, and print the strings
3913d8817e4Smiod in the initialized data section(s).
3923d8817e4Smiod
3933d8817e4Smiod Return TRUE if successful,
3943d8817e4Smiod FALSE if not (such as if FILE is not an object file). */
3953d8817e4Smiod
3963d8817e4Smiod static bfd_boolean
strings_object_file(const char * file)3973d8817e4Smiod strings_object_file (const char *file)
3983d8817e4Smiod {
3993d8817e4Smiod filename_and_size_t filename_and_size;
4003d8817e4Smiod bfd *abfd;
4013d8817e4Smiod
4023d8817e4Smiod abfd = bfd_openr (file, target);
4033d8817e4Smiod
4043d8817e4Smiod if (abfd == NULL)
4053d8817e4Smiod /* Treat the file as a non-object file. */
4063d8817e4Smiod return FALSE;
4073d8817e4Smiod
4083d8817e4Smiod /* This call is mainly for its side effect of reading in the sections.
4093d8817e4Smiod We follow the traditional behavior of `strings' in that we don't
4103d8817e4Smiod complain if we don't recognize a file to be an object file. */
4113d8817e4Smiod if (!bfd_check_format (abfd, bfd_object))
4123d8817e4Smiod {
4133d8817e4Smiod bfd_close (abfd);
4143d8817e4Smiod return FALSE;
4153d8817e4Smiod }
4163d8817e4Smiod
4173d8817e4Smiod got_a_section = FALSE;
4183d8817e4Smiod filename_and_size.filename = file;
4193d8817e4Smiod filename_and_size.filesize = 0;
4203d8817e4Smiod bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
4213d8817e4Smiod
4223d8817e4Smiod if (!bfd_close (abfd))
4233d8817e4Smiod {
4243d8817e4Smiod bfd_nonfatal (file);
4253d8817e4Smiod return FALSE;
4263d8817e4Smiod }
4273d8817e4Smiod
4283d8817e4Smiod return got_a_section;
4293d8817e4Smiod }
4303d8817e4Smiod
4313d8817e4Smiod /* Print the strings in FILE. Return TRUE if ok, FALSE if an error occurs. */
4323d8817e4Smiod
4333d8817e4Smiod static bfd_boolean
strings_file(char * file)4343d8817e4Smiod strings_file (char *file)
4353d8817e4Smiod {
4363d8817e4Smiod statbuf st;
4373d8817e4Smiod
4383d8817e4Smiod if (file_stat (file, &st) < 0)
4393d8817e4Smiod {
4403d8817e4Smiod if (errno == ENOENT)
4413d8817e4Smiod non_fatal (_("'%s': No such file"), file);
4423d8817e4Smiod else
4433d8817e4Smiod non_fatal (_("Warning: could not locate '%s'. reason: %s"),
4443d8817e4Smiod file, strerror (errno));
4453d8817e4Smiod return FALSE;
4463d8817e4Smiod }
4473d8817e4Smiod
4483d8817e4Smiod /* If we weren't told to scan the whole file,
4493d8817e4Smiod try to open it as an object file and only look at
4503d8817e4Smiod initialized data sections. If that fails, fall back to the
4513d8817e4Smiod whole file. */
4523d8817e4Smiod if (!datasection_only || !strings_object_file (file))
4533d8817e4Smiod {
4543d8817e4Smiod FILE *stream;
4553d8817e4Smiod
4563d8817e4Smiod stream = file_open (file, FOPEN_RB);
4573d8817e4Smiod if (stream == NULL)
4583d8817e4Smiod {
4593d8817e4Smiod fprintf (stderr, "%s: ", program_name);
4603d8817e4Smiod perror (file);
4613d8817e4Smiod return FALSE;
4623d8817e4Smiod }
4633d8817e4Smiod
4643d8817e4Smiod print_strings (file, stream, (file_off) 0, 0, 0, (char *) 0);
4653d8817e4Smiod
4663d8817e4Smiod if (fclose (stream) == EOF)
4673d8817e4Smiod {
4683d8817e4Smiod fprintf (stderr, "%s: ", program_name);
4693d8817e4Smiod perror (file);
4703d8817e4Smiod return FALSE;
4713d8817e4Smiod }
4723d8817e4Smiod }
4733d8817e4Smiod
4743d8817e4Smiod return TRUE;
4753d8817e4Smiod }
4763d8817e4Smiod
4773d8817e4Smiod /* Read the next character, return EOF if none available.
4783d8817e4Smiod Assume that STREAM is positioned so that the next byte read
4793d8817e4Smiod is at address ADDRESS in the file.
4803d8817e4Smiod
4813d8817e4Smiod If STREAM is NULL, do not read from it.
4823d8817e4Smiod The caller can supply a buffer of characters
4833d8817e4Smiod to be processed before the data in STREAM.
4843d8817e4Smiod MAGIC is the address of the buffer and
4853d8817e4Smiod MAGICCOUNT is how many characters are in it. */
4863d8817e4Smiod
4873d8817e4Smiod static long
get_char(FILE * stream,file_off * address,int * magiccount,char ** magic)4883d8817e4Smiod get_char (FILE *stream, file_off *address, int *magiccount, char **magic)
4893d8817e4Smiod {
4903d8817e4Smiod int c, i;
4913d8817e4Smiod long r = EOF;
4923d8817e4Smiod unsigned char buf[4];
4933d8817e4Smiod
4943d8817e4Smiod for (i = 0; i < encoding_bytes; i++)
4953d8817e4Smiod {
4963d8817e4Smiod if (*magiccount)
4973d8817e4Smiod {
4983d8817e4Smiod (*magiccount)--;
4993d8817e4Smiod c = *(*magic)++;
5003d8817e4Smiod }
5013d8817e4Smiod else
5023d8817e4Smiod {
5033d8817e4Smiod if (stream == NULL)
5043d8817e4Smiod return EOF;
5053d8817e4Smiod
5063d8817e4Smiod /* Only use getc_unlocked if we found a declaration for it.
5073d8817e4Smiod Otherwise, libc is not thread safe by default, and we
5083d8817e4Smiod should not use it. */
5093d8817e4Smiod
5103d8817e4Smiod #if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
5113d8817e4Smiod c = getc_unlocked (stream);
5123d8817e4Smiod #else
5133d8817e4Smiod c = getc (stream);
5143d8817e4Smiod #endif
5153d8817e4Smiod if (c == EOF)
5163d8817e4Smiod return EOF;
5173d8817e4Smiod }
5183d8817e4Smiod
5193d8817e4Smiod (*address)++;
5203d8817e4Smiod buf[i] = c;
5213d8817e4Smiod }
5223d8817e4Smiod
5233d8817e4Smiod switch (encoding)
5243d8817e4Smiod {
5253d8817e4Smiod case 'S':
5263d8817e4Smiod case 's':
5273d8817e4Smiod r = buf[0];
5283d8817e4Smiod break;
5293d8817e4Smiod case 'b':
5303d8817e4Smiod r = (buf[0] << 8) | buf[1];
5313d8817e4Smiod break;
5323d8817e4Smiod case 'l':
5333d8817e4Smiod r = buf[0] | (buf[1] << 8);
5343d8817e4Smiod break;
5353d8817e4Smiod case 'B':
5363d8817e4Smiod r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
5373d8817e4Smiod ((long) buf[2] << 8) | buf[3];
5383d8817e4Smiod break;
5393d8817e4Smiod case 'L':
5403d8817e4Smiod r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
5413d8817e4Smiod ((long) buf[3] << 24);
5423d8817e4Smiod break;
5433d8817e4Smiod }
5443d8817e4Smiod
5453d8817e4Smiod if (r == EOF)
5463d8817e4Smiod return 0;
5473d8817e4Smiod
5483d8817e4Smiod return r;
5493d8817e4Smiod }
5503d8817e4Smiod
5513d8817e4Smiod /* Find the strings in file FILENAME, read from STREAM.
5523d8817e4Smiod Assume that STREAM is positioned so that the next byte read
5533d8817e4Smiod is at address ADDRESS in the file.
5543d8817e4Smiod Stop reading at address STOP_POINT in the file, if nonzero.
5553d8817e4Smiod
5563d8817e4Smiod If STREAM is NULL, do not read from it.
5573d8817e4Smiod The caller can supply a buffer of characters
5583d8817e4Smiod to be processed before the data in STREAM.
5593d8817e4Smiod MAGIC is the address of the buffer and
5603d8817e4Smiod MAGICCOUNT is how many characters are in it.
5613d8817e4Smiod Those characters come at address ADDRESS and the data in STREAM follow. */
5623d8817e4Smiod
5633d8817e4Smiod static void
print_strings(const char * filename,FILE * stream,file_off address,int stop_point,int magiccount,char * magic)5643d8817e4Smiod print_strings (const char *filename, FILE *stream, file_off address,
5653d8817e4Smiod int stop_point, int magiccount, char *magic)
5663d8817e4Smiod {
5673d8817e4Smiod char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
5683d8817e4Smiod
5693d8817e4Smiod while (1)
5703d8817e4Smiod {
5713d8817e4Smiod file_off start;
5723d8817e4Smiod int i;
5733d8817e4Smiod long c;
5743d8817e4Smiod
5753d8817e4Smiod /* See if the next `string_min' chars are all graphic chars. */
5763d8817e4Smiod tryline:
5773d8817e4Smiod if (stop_point && address >= stop_point)
5783d8817e4Smiod break;
5793d8817e4Smiod start = address;
5803d8817e4Smiod for (i = 0; i < string_min; i++)
5813d8817e4Smiod {
5823d8817e4Smiod c = get_char (stream, &address, &magiccount, &magic);
5833d8817e4Smiod if (c == EOF)
5843d8817e4Smiod return;
5853d8817e4Smiod if (! STRING_ISGRAPHIC (c))
5863d8817e4Smiod /* Found a non-graphic. Try again starting with next char. */
5873d8817e4Smiod goto tryline;
5883d8817e4Smiod buf[i] = c;
5893d8817e4Smiod }
5903d8817e4Smiod
5913d8817e4Smiod /* We found a run of `string_min' graphic characters. Print up
5923d8817e4Smiod to the next non-graphic character. */
5933d8817e4Smiod
5943d8817e4Smiod if (print_filenames)
5953d8817e4Smiod printf ("%s: ", filename);
5963d8817e4Smiod if (print_addresses)
5973d8817e4Smiod switch (address_radix)
5983d8817e4Smiod {
5993d8817e4Smiod case 8:
6003d8817e4Smiod #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
6013d8817e4Smiod if (sizeof (start) > sizeof (long))
6023d8817e4Smiod printf ("%7Lo ", (unsigned long long) start);
6033d8817e4Smiod else
6043d8817e4Smiod #else
6053d8817e4Smiod # if !BFD_HOST_64BIT_LONG
6063d8817e4Smiod if (start != (unsigned long) start)
6073d8817e4Smiod printf ("++%7lo ", (unsigned long) start);
6083d8817e4Smiod else
6093d8817e4Smiod # endif
6103d8817e4Smiod #endif
6113d8817e4Smiod printf ("%7lo ", (unsigned long) start);
6123d8817e4Smiod break;
6133d8817e4Smiod
6143d8817e4Smiod case 10:
6153d8817e4Smiod #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
6163d8817e4Smiod if (sizeof (start) > sizeof (long))
617*c9d03015Sjsg printf ("%7lld ", (unsigned long long) start);
6183d8817e4Smiod else
6193d8817e4Smiod #else
6203d8817e4Smiod # if !BFD_HOST_64BIT_LONG
6213d8817e4Smiod if (start != (unsigned long) start)
6223d8817e4Smiod printf ("++%7ld ", (unsigned long) start);
6233d8817e4Smiod else
6243d8817e4Smiod # endif
6253d8817e4Smiod #endif
6263d8817e4Smiod printf ("%7ld ", (long) start);
6273d8817e4Smiod break;
6283d8817e4Smiod
6293d8817e4Smiod case 16:
6303d8817e4Smiod #if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
6313d8817e4Smiod if (sizeof (start) > sizeof (long))
632*c9d03015Sjsg printf ("%7llx ", (unsigned long long) start);
6333d8817e4Smiod else
6343d8817e4Smiod #else
6353d8817e4Smiod # if !BFD_HOST_64BIT_LONG
6363d8817e4Smiod if (start != (unsigned long) start)
6373d8817e4Smiod printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
6383d8817e4Smiod (unsigned long) (start & 0xffffffff));
6393d8817e4Smiod else
6403d8817e4Smiod # endif
6413d8817e4Smiod #endif
6423d8817e4Smiod printf ("%7lx ", (unsigned long) start);
6433d8817e4Smiod break;
6443d8817e4Smiod }
6453d8817e4Smiod
6463d8817e4Smiod buf[i] = '\0';
6473d8817e4Smiod fputs (buf, stdout);
6483d8817e4Smiod
6493d8817e4Smiod while (1)
6503d8817e4Smiod {
6513d8817e4Smiod c = get_char (stream, &address, &magiccount, &magic);
6523d8817e4Smiod if (c == EOF)
6533d8817e4Smiod break;
6543d8817e4Smiod if (! STRING_ISGRAPHIC (c))
6553d8817e4Smiod break;
6563d8817e4Smiod putchar (c);
6573d8817e4Smiod }
6583d8817e4Smiod
6593d8817e4Smiod putchar ('\n');
6603d8817e4Smiod }
6613d8817e4Smiod }
6623d8817e4Smiod
6633d8817e4Smiod /* Parse string S as an integer, using decimal radix by default,
6643d8817e4Smiod but allowing octal and hex numbers as in C. */
6653d8817e4Smiod
6663d8817e4Smiod static int
integer_arg(char * s)6673d8817e4Smiod integer_arg (char *s)
6683d8817e4Smiod {
6693d8817e4Smiod int value;
6703d8817e4Smiod int radix = 10;
6713d8817e4Smiod char *p = s;
6723d8817e4Smiod int c;
6733d8817e4Smiod
6743d8817e4Smiod if (*p != '0')
6753d8817e4Smiod radix = 10;
6763d8817e4Smiod else if (*++p == 'x')
6773d8817e4Smiod {
6783d8817e4Smiod radix = 16;
6793d8817e4Smiod p++;
6803d8817e4Smiod }
6813d8817e4Smiod else
6823d8817e4Smiod radix = 8;
6833d8817e4Smiod
6843d8817e4Smiod value = 0;
6853d8817e4Smiod while (((c = *p++) >= '0' && c <= '9')
6863d8817e4Smiod || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
6873d8817e4Smiod {
6883d8817e4Smiod value *= radix;
6893d8817e4Smiod if (c >= '0' && c <= '9')
6903d8817e4Smiod value += c - '0';
6913d8817e4Smiod else
6923d8817e4Smiod value += (c & ~40) - 'A';
6933d8817e4Smiod }
6943d8817e4Smiod
6953d8817e4Smiod if (c == 'b')
6963d8817e4Smiod value *= 512;
6973d8817e4Smiod else if (c == 'B')
6983d8817e4Smiod value *= 1024;
6993d8817e4Smiod else
7003d8817e4Smiod p--;
7013d8817e4Smiod
7023d8817e4Smiod if (*p)
7033d8817e4Smiod fatal (_("invalid integer argument %s"), s);
7043d8817e4Smiod
7053d8817e4Smiod return value;
7063d8817e4Smiod }
7073d8817e4Smiod
7083d8817e4Smiod static void
usage(FILE * stream,int status)7093d8817e4Smiod usage (FILE *stream, int status)
7103d8817e4Smiod {
7113d8817e4Smiod fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
7123d8817e4Smiod fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
7133d8817e4Smiod fprintf (stream, _(" The options are:\n\
7143d8817e4Smiod -a - --all Scan the entire file, not just the data section\n\
7153d8817e4Smiod -f --print-file-name Print the name of the file before each string\n\
7163d8817e4Smiod -n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
7173d8817e4Smiod -<number> least [number] characters (default 4).\n\
7183d8817e4Smiod -t --radix={o,d,x} Print the location of the string in base 8, 10 or 16\n\
7193d8817e4Smiod -o An alias for --radix=o\n\
7203d8817e4Smiod -T --target=<BFDNAME> Specify the binary file format\n\
7213d8817e4Smiod -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
7223d8817e4Smiod s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
7233d8817e4Smiod @<file> Read options from <file>\n\
7243d8817e4Smiod -h --help Display this information\n\
7253d8817e4Smiod -v --version Print the program's version number\n"));
7263d8817e4Smiod list_supported_targets (program_name, stream);
7273d8817e4Smiod if (status == 0)
7283d8817e4Smiod fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
7293d8817e4Smiod exit (status);
7303d8817e4Smiod }
731