OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [binutils/] [strings.c] - Blame information for rev 100

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 15 khays
/* strings -- print the strings of printable characters in files
2
   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3
   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
4
   Free Software Foundation, Inc.
5
 
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
 
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19
   02110-1301, USA.  */
20
 
21
/* Usage: strings [options] file...
22
 
23
   Options:
24
   --all
25
   -a
26
   -            Do not scan only the initialized data section of object files.
27
 
28
   --print-file-name
29
   -f           Print the name of the file before each string.
30
 
31
   --bytes=min-len
32
   -n min-len
33
   -min-len     Print graphic char sequences, MIN-LEN or more bytes long,
34
                that are followed by a NUL or a newline.  Default is 4.
35
 
36
   --radix={o,x,d}
37
   -t {o,x,d}   Print the offset within the file before each string,
38
                in octal/hex/decimal.
39
 
40
   -o           Like -to.  (Some other implementations have -o like -to,
41
                others like -td.  We chose one arbitrarily.)
42
 
43
   --encoding={s,S,b,l,B,L}
44
   -e {s,S,b,l,B,L}
45
                Select character encoding: 7-bit-character, 8-bit-character,
46
                bigendian 16-bit, littleendian 16-bit, bigendian 32-bit,
47
                littleendian 32-bit.
48
 
49
   --target=BFDNAME
50
   -T {bfdname}
51
                Specify a non-default object file format.
52
 
53
   --help
54
   -h           Print the usage message on the standard output.
55
 
56
   --version
57
   -V
58
   -v           Print the program version number.
59
 
60
   Written by Richard Stallman <rms@gnu.ai.mit.edu>
61
   and David MacKenzie <djm@gnu.ai.mit.edu>.  */
62
 
63
#include "sysdep.h"
64
#include "bfd.h"
65
#include "getopt.h"
66
#include "libiberty.h"
67
#include "safe-ctype.h"
68
#include <sys/stat.h>
69
#include "bucomm.h"
70
 
71
#define STRING_ISGRAPHIC(c) \
72
      (   (c) >= 0 \
73
       && (c) <= 255 \
74
       && ((c) == '\t' || ISPRINT (c) || (encoding == 'S' && (c) > 127)))
75
 
76
#ifndef errno
77
extern int errno;
78
#endif
79
 
80
/* The BFD section flags that identify an initialized data section.  */
81
#define DATA_FLAGS (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS)
82
 
83
/* Radix for printing addresses (must be 8, 10 or 16).  */
84
static int address_radix;
85
 
86
/* Minimum length of sequence of graphic chars to trigger output.  */
87
static int string_min;
88
 
89
/* TRUE means print address within file for each string.  */
90
static bfd_boolean print_addresses;
91
 
92
/* TRUE means print filename for each string.  */
93
static bfd_boolean print_filenames;
94
 
95
/* TRUE means for object files scan only the data section.  */
96
static bfd_boolean datasection_only;
97
 
98
/* TRUE if we found an initialized data section in the current file.  */
99
static bfd_boolean got_a_section;
100
 
101
/* The BFD object file format.  */
102
static char *target;
103
 
104
/* The character encoding format.  */
105
static char encoding;
106
static int encoding_bytes;
107
 
108
static struct option long_options[] =
109
{
110
  {"all", no_argument, NULL, 'a'},
111
  {"print-file-name", no_argument, NULL, 'f'},
112
  {"bytes", required_argument, NULL, 'n'},
113
  {"radix", required_argument, NULL, 't'},
114
  {"encoding", required_argument, NULL, 'e'},
115
  {"target", required_argument, NULL, 'T'},
116
  {"help", no_argument, NULL, 'h'},
117
  {"version", no_argument, NULL, 'v'},
118
  {NULL, 0, NULL, 0}
119
};
120
 
121
/* Records the size of a named file so that we
122
   do not repeatedly run bfd_stat() on it.  */
123
 
124
typedef struct
125
{
126
  const char *  filename;
127
  bfd_size_type filesize;
128
} filename_and_size_t;
129
 
130
static void strings_a_section (bfd *, asection *, void *);
131
static bfd_boolean strings_object_file (const char *);
132
static bfd_boolean strings_file (char *file);
133
static void print_strings (const char *, FILE *, file_ptr, int, int, char *);
134
static void usage (FILE *, int);
135
static long get_char (FILE *, file_ptr *, int *, char **);
136
 
137
int main (int, char **);
138
 
139
int
140
main (int argc, char **argv)
141
{
142
  int optc;
143
  int exit_status = 0;
144
  bfd_boolean files_given = FALSE;
145
  char *s;
146
  int numeric_opt = 0;
147
 
148
#if defined (HAVE_SETLOCALE)
149
  setlocale (LC_ALL, "");
150
#endif
151
  bindtextdomain (PACKAGE, LOCALEDIR);
152
  textdomain (PACKAGE);
153
 
154
  program_name = argv[0];
155
  xmalloc_set_program_name (program_name);
156
 
157
  expandargv (&argc, &argv);
158
 
159
  string_min = 4;
160
  print_addresses = FALSE;
161
  print_filenames = FALSE;
162
  datasection_only = TRUE;
163
  target = NULL;
164
  encoding = 's';
165
 
166
  while ((optc = getopt_long (argc, argv, "afhHn:ot:e:T:Vv0123456789",
167
                              long_options, (int *) 0)) != EOF)
168
    {
169
      switch (optc)
170
        {
171
        case 'a':
172
          datasection_only = FALSE;
173
          break;
174
 
175
        case 'f':
176
          print_filenames = TRUE;
177
          break;
178
 
179
        case 'H':
180
        case 'h':
181
          usage (stdout, 0);
182
 
183
        case 'n':
184
          string_min = (int) strtoul (optarg, &s, 0);
185
          if (s != NULL && *s != 0)
186
            fatal (_("invalid integer argument %s"), optarg);
187
          break;
188
 
189
        case 'o':
190
          print_addresses = TRUE;
191
          address_radix = 8;
192
          break;
193
 
194
        case 't':
195
          print_addresses = TRUE;
196
          if (optarg[1] != '\0')
197
            usage (stderr, 1);
198
          switch (optarg[0])
199
            {
200
            case 'o':
201
              address_radix = 8;
202
              break;
203
 
204
            case 'd':
205
              address_radix = 10;
206
              break;
207
 
208
            case 'x':
209
              address_radix = 16;
210
              break;
211
 
212
            default:
213
              usage (stderr, 1);
214
            }
215
          break;
216
 
217
        case 'T':
218
          target = optarg;
219
          break;
220
 
221
        case 'e':
222
          if (optarg[1] != '\0')
223
            usage (stderr, 1);
224
          encoding = optarg[0];
225
          break;
226
 
227
        case 'V':
228
        case 'v':
229
          print_version ("strings");
230
          break;
231
 
232
        case '?':
233
          usage (stderr, 1);
234
 
235
        default:
236
          numeric_opt = optind;
237
          break;
238
        }
239
    }
240
 
241
  if (numeric_opt != 0)
242
    {
243
      string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0);
244
      if (s != NULL && *s != 0)
245
        fatal (_("invalid integer argument %s"), argv[numeric_opt - 1] + 1);
246
    }
247
  if (string_min < 1)
248
    fatal (_("invalid minimum string length %d"), string_min);
249
 
250
  switch (encoding)
251
    {
252
    case 'S':
253
    case 's':
254
      encoding_bytes = 1;
255
      break;
256
    case 'b':
257
    case 'l':
258
      encoding_bytes = 2;
259
      break;
260
    case 'B':
261
    case 'L':
262
      encoding_bytes = 4;
263
      break;
264
    default:
265
      usage (stderr, 1);
266
    }
267
 
268
  bfd_init ();
269
  set_default_bfd_target ();
270
 
271
  if (optind >= argc)
272
    {
273
      datasection_only = FALSE;
274
      SET_BINARY (fileno (stdin));
275
      print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
276
      files_given = TRUE;
277
    }
278
  else
279
    {
280
      for (; optind < argc; ++optind)
281
        {
282
          if (strcmp (argv[optind], "-") == 0)
283
            datasection_only = FALSE;
284
          else
285
            {
286
              files_given = TRUE;
287
              exit_status |= strings_file (argv[optind]) == FALSE;
288
            }
289
        }
290
    }
291
 
292
  if (!files_given)
293
    usage (stderr, 1);
294
 
295
  return (exit_status);
296
}
297
 
298
/* Scan section SECT of the file ABFD, whose printable name is in
299
   ARG->filename and whose size might be in ARG->filesize.  If it
300
   contains initialized data set `got_a_section' and print the
301
   strings in it.
302
 
303
   FIXME: We ought to be able to return error codes/messages for
304
   certain conditions.  */
305
 
306
static void
307
strings_a_section (bfd *abfd, asection *sect, void *arg)
308
{
309
  filename_and_size_t * filename_and_sizep;
310
  bfd_size_type *filesizep;
311
  bfd_size_type sectsize;
312
  void *mem;
313
 
314
  if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
315
    return;
316
 
317
  sectsize = bfd_get_section_size (sect);
318
 
319
  if (sectsize <= 0)
320
    return;
321
 
322
  /* Get the size of the file.  This might have been cached for us.  */
323
  filename_and_sizep = (filename_and_size_t *) arg;
324
  filesizep = & filename_and_sizep->filesize;
325
 
326
  if (*filesizep == 0)
327
    {
328
      struct stat st;
329
 
330
      if (bfd_stat (abfd, &st))
331
        return;
332
 
333
      /* Cache the result so that we do not repeatedly stat this file.  */
334
      *filesizep = st.st_size;
335
    }
336
 
337
  /* Compare the size of the section against the size of the file.
338
     If the section is bigger then the file must be corrupt and
339
     we should not try dumping it.  */
340
  if (sectsize >= *filesizep)
341
    return;
342
 
343
  mem = xmalloc (sectsize);
344
 
345
  if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sectsize))
346
    {
347
      got_a_section = TRUE;
348
 
349
      print_strings (filename_and_sizep->filename, NULL, sect->filepos,
350
                     0, sectsize, (char *) mem);
351
    }
352
 
353
  free (mem);
354
}
355
 
356
/* Scan all of the sections in FILE, and print the strings
357
   in the initialized data section(s).
358
 
359
   Return TRUE if successful,
360
   FALSE if not (such as if FILE is not an object file).  */
361
 
362
static bfd_boolean
363
strings_object_file (const char *file)
364
{
365
  filename_and_size_t filename_and_size;
366
  bfd *abfd;
367
 
368
  abfd = bfd_openr (file, target);
369
 
370
  if (abfd == NULL)
371
    /* Treat the file as a non-object file.  */
372
    return FALSE;
373
 
374
  /* This call is mainly for its side effect of reading in the sections.
375
     We follow the traditional behavior of `strings' in that we don't
376
     complain if we don't recognize a file to be an object file.  */
377
  if (!bfd_check_format (abfd, bfd_object))
378
    {
379
      bfd_close (abfd);
380
      return FALSE;
381
    }
382
 
383
  got_a_section = FALSE;
384
  filename_and_size.filename = file;
385
  filename_and_size.filesize = 0;
386
  bfd_map_over_sections (abfd, strings_a_section, & filename_and_size);
387
 
388
  if (!bfd_close (abfd))
389
    {
390
      bfd_nonfatal (file);
391
      return FALSE;
392
    }
393
 
394
  return got_a_section;
395
}
396
 
397
/* Print the strings in FILE.  Return TRUE if ok, FALSE if an error occurs.  */
398
 
399
static bfd_boolean
400
strings_file (char *file)
401
{
402
  struct stat st;
403
 
404
  /* get_file_size does not support non-S_ISREG files.  */
405
 
406
  if (stat (file, &st) < 0)
407
    {
408
      if (errno == ENOENT)
409
        non_fatal (_("'%s': No such file"), file);
410
      else
411
        non_fatal (_("Warning: could not locate '%s'.  reason: %s"),
412
                   file, strerror (errno));
413
      return FALSE;
414
    }
415
 
416
  /* If we weren't told to scan the whole file,
417
     try to open it as an object file and only look at
418
     initialized data sections.  If that fails, fall back to the
419
     whole file.  */
420
  if (!datasection_only || !strings_object_file (file))
421
    {
422
      FILE *stream;
423
 
424
      stream = fopen (file, FOPEN_RB);
425
      if (stream == NULL)
426
        {
427
          fprintf (stderr, "%s: ", program_name);
428
          perror (file);
429
          return FALSE;
430
        }
431
 
432
      print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
433
 
434
      if (fclose (stream) == EOF)
435
        {
436
          fprintf (stderr, "%s: ", program_name);
437
          perror (file);
438
          return FALSE;
439
        }
440
    }
441
 
442
  return TRUE;
443
}
444
 
445
/* Read the next character, return EOF if none available.
446
   Assume that STREAM is positioned so that the next byte read
447
   is at address ADDRESS in the file.
448
 
449
   If STREAM is NULL, do not read from it.
450
   The caller can supply a buffer of characters
451
   to be processed before the data in STREAM.
452
   MAGIC is the address of the buffer and
453
   MAGICCOUNT is how many characters are in it.  */
454
 
455
static long
456
get_char (FILE *stream, file_ptr *address, int *magiccount, char **magic)
457
{
458
  int c, i;
459
  long r = EOF;
460
  unsigned char buf[4];
461
 
462
  for (i = 0; i < encoding_bytes; i++)
463
    {
464
      if (*magiccount)
465
        {
466
          (*magiccount)--;
467
          c = *(*magic)++;
468
        }
469
      else
470
        {
471
          if (stream == NULL)
472
            return EOF;
473
 
474
          /* Only use getc_unlocked if we found a declaration for it.
475
             Otherwise, libc is not thread safe by default, and we
476
             should not use it.  */
477
 
478
#if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
479
          c = getc_unlocked (stream);
480
#else
481
          c = getc (stream);
482
#endif
483
          if (c == EOF)
484
            return EOF;
485
        }
486
 
487
      (*address)++;
488
      buf[i] = c;
489
    }
490
 
491
  switch (encoding)
492
    {
493
    case 'S':
494
    case 's':
495
      r = buf[0];
496
      break;
497
    case 'b':
498
      r = (buf[0] << 8) | buf[1];
499
      break;
500
    case 'l':
501
      r = buf[0] | (buf[1] << 8);
502
      break;
503
    case 'B':
504
      r = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
505
        ((long) buf[2] << 8) | buf[3];
506
      break;
507
    case 'L':
508
      r = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
509
        ((long) buf[3] << 24);
510
      break;
511
    }
512
 
513
  if (r == EOF)
514
    return 0;
515
 
516
  return r;
517
}
518
 
519
/* Find the strings in file FILENAME, read from STREAM.
520
   Assume that STREAM is positioned so that the next byte read
521
   is at address ADDRESS in the file.
522
   Stop reading at address STOP_POINT in the file, if nonzero.
523
 
524
   If STREAM is NULL, do not read from it.
525
   The caller can supply a buffer of characters
526
   to be processed before the data in STREAM.
527
   MAGIC is the address of the buffer and
528
   MAGICCOUNT is how many characters are in it.
529
   Those characters come at address ADDRESS and the data in STREAM follow.  */
530
 
531
static void
532
print_strings (const char *filename, FILE *stream, file_ptr address,
533
               int stop_point, int magiccount, char *magic)
534
{
535
  char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
536
 
537
  while (1)
538
    {
539
      file_ptr start;
540
      int i;
541
      long c;
542
 
543
      /* See if the next `string_min' chars are all graphic chars.  */
544
    tryline:
545
      if (stop_point && address >= stop_point)
546
        break;
547
      start = address;
548
      for (i = 0; i < string_min; i++)
549
        {
550
          c = get_char (stream, &address, &magiccount, &magic);
551
          if (c == EOF)
552
            {
553
              free (buf);
554
              return;
555
            }
556
          if (! STRING_ISGRAPHIC (c))
557
            /* Found a non-graphic.  Try again starting with next char.  */
558
            goto tryline;
559
          buf[i] = c;
560
        }
561
 
562
      /* We found a run of `string_min' graphic characters.  Print up
563
         to the next non-graphic character.  */
564
 
565
      if (print_filenames)
566
        printf ("%s: ", filename);
567
      if (print_addresses)
568
        switch (address_radix)
569
          {
570
          case 8:
571
#if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
572
            if (sizeof (start) > sizeof (long))
573
              {
574
#ifndef __MSVCRT__
575
                printf ("%7llo ", (unsigned long long) start);
576
#else
577
                printf ("%7I64o ", (unsigned long long) start);
578
#endif
579
              }
580
            else
581
#elif !BFD_HOST_64BIT_LONG
582
            if (start != (unsigned long) start)
583
              printf ("++%7lo ", (unsigned long) start);
584
            else
585
#endif
586
              printf ("%7lo ", (unsigned long) start);
587
            break;
588
 
589
          case 10:
590
#if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
591
            if (sizeof (start) > sizeof (long))
592
              {
593
#ifndef __MSVCRT__
594
                printf ("%7lld ", (unsigned long long) start);
595
#else
596
                printf ("%7I64d ", (unsigned long long) start);
597
#endif
598
              }
599
            else
600
#elif !BFD_HOST_64BIT_LONG
601
            if (start != (unsigned long) start)
602
              printf ("++%7ld ", (unsigned long) start);
603
            else
604
#endif
605
              printf ("%7ld ", (long) start);
606
            break;
607
 
608
          case 16:
609
#if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
610
            if (sizeof (start) > sizeof (long))
611
              {
612
#ifndef __MSVCRT__
613
                printf ("%7llx ", (unsigned long long) start);
614
#else
615
                printf ("%7I64x ", (unsigned long long) start);
616
#endif
617
              }
618
            else
619
#elif !BFD_HOST_64BIT_LONG
620
            if (start != (unsigned long) start)
621
              printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
622
                      (unsigned long) (start & 0xffffffff));
623
            else
624
#endif
625
              printf ("%7lx ", (unsigned long) start);
626
            break;
627
          }
628
 
629
      buf[i] = '\0';
630
      fputs (buf, stdout);
631
 
632
      while (1)
633
        {
634
          c = get_char (stream, &address, &magiccount, &magic);
635
          if (c == EOF)
636
            break;
637
          if (! STRING_ISGRAPHIC (c))
638
            break;
639
          putchar (c);
640
        }
641
 
642
      putchar ('\n');
643
    }
644
  free (buf);
645
}
646
 
647
static void
648
usage (FILE *stream, int status)
649
{
650
  fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
651
  fprintf (stream, _(" Display printable strings in [file(s)] (stdin by default)\n"));
652
  fprintf (stream, _(" The options are:\n\
653
  -a - --all                Scan the entire file, not just the data section\n\
654
  -f --print-file-name      Print the name of the file before each string\n\
655
  -n --bytes=[number]       Locate & print any NUL-terminated sequence of at\n\
656
  -<number>                   least [number] characters (default 4).\n\
657
  -t --radix={o,d,x}        Print the location of the string in base 8, 10 or 16\n\
658
  -o                        An alias for --radix=o\n\
659
  -T --target=<BFDNAME>     Specify the binary file format\n\
660
  -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
661
                            s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
662
  @<file>                   Read options from <file>\n\
663
  -h --help                 Display this information\n\
664
  -v -V --version           Print the program's version number\n"));
665
  list_supported_targets (program_name, stream);
666
  if (REPORT_BUGS_TO[0] && status == 0)
667
    fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
668
  exit (status);
669
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.