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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [binutils/] [size.c] - Blame information for rev 853

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

Line No. Rev Author Line
1 38 julius
/* size.c -- report size of various sections of an executable file.
2
   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3
   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
4
 
5
   This file is part of GNU Binutils.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
/* Extensions/incompatibilities:
23
   o - BSD output has filenames at the end.
24
   o - BSD output can appear in different radicies.
25
   o - SysV output has less redundant whitespace.  Filename comes at end.
26
   o - SysV output doesn't show VMA which is always the same as the PMA.
27
   o - We also handle core files.
28
   o - We also handle archives.
29
   If you write shell scripts which manipulate this info then you may be
30
   out of luck; there's no --compatibility or --pedantic option.  */
31
 
32
#include "sysdep.h"
33
#include "bfd.h"
34
#include "libiberty.h"
35
#include "getopt.h"
36
#include "bucomm.h"
37
 
38
#ifndef BSD_DEFAULT
39
#define BSD_DEFAULT 1
40
#endif
41
 
42
/* Program options.  */
43
 
44
static enum
45
  {
46
    decimal, octal, hex
47
  }
48
radix = decimal;
49
 
50
/* 0 means use AT&T-style output.  */
51
static int berkeley_format = BSD_DEFAULT;
52
 
53
static int show_version = 0;
54
static int show_help = 0;
55
static int show_totals = 0;
56
static int show_common = 0;
57
 
58
static bfd_size_type common_size;
59
static bfd_size_type total_bsssize;
60
static bfd_size_type total_datasize;
61
static bfd_size_type total_textsize;
62
 
63
/* Program exit status.  */
64
static int return_code = 0;
65
 
66
static char *target = NULL;
67
 
68
/* Forward declarations.  */
69
 
70
static void display_file (char *);
71
static void rprint_number (int, bfd_size_type);
72
static void print_sizes (bfd * file);
73
 
74
static void
75
usage (FILE *stream, int status)
76
{
77
  fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
78
  fprintf (stream, _(" Displays the sizes of sections inside binary files\n"));
79
  fprintf (stream, _(" If no input file(s) are specified, a.out is assumed\n"));
80
  fprintf (stream, _(" The options are:\n\
81
  -A|-B     --format={sysv|berkeley}  Select output style (default is %s)\n\
82
  -o|-d|-x  --radix={8|10|16}         Display numbers in octal, decimal or hex\n\
83
  -t        --totals                  Display the total sizes (Berkeley only)\n\
84
            --common                  Display total size for *COM* syms\n\
85
            --target=<bfdname>        Set the binary file format\n\
86
            @<file>                   Read options from <file>\n\
87
  -h        --help                    Display this information\n\
88
  -v        --version                 Display the program's version\n\
89
\n"),
90
#if BSD_DEFAULT
91
  "berkeley"
92
#else
93
  "sysv"
94
#endif
95
);
96
  list_supported_targets (program_name, stream);
97
  if (REPORT_BUGS_TO[0] && status == 0)
98
    fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
99
  exit (status);
100
}
101
 
102
#define OPTION_FORMAT (200)
103
#define OPTION_RADIX (OPTION_FORMAT + 1)
104
#define OPTION_TARGET (OPTION_RADIX + 1)
105
 
106
static struct option long_options[] =
107
{
108
  {"common", no_argument, &show_common, 1},
109
  {"format", required_argument, 0, OPTION_FORMAT},
110
  {"radix", required_argument, 0, OPTION_RADIX},
111
  {"target", required_argument, 0, OPTION_TARGET},
112
  {"totals", no_argument, &show_totals, 1},
113
  {"version", no_argument, &show_version, 1},
114
  {"help", no_argument, &show_help, 1},
115
  {0, no_argument, 0, 0}
116
};
117
 
118
int main (int, char **);
119
 
120
int
121
main (int argc, char **argv)
122
{
123
  int temp;
124
  int c;
125
 
126
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
127
  setlocale (LC_MESSAGES, "");
128
#endif
129
#if defined (HAVE_SETLOCALE)
130
  setlocale (LC_CTYPE, "");
131
#endif
132
  bindtextdomain (PACKAGE, LOCALEDIR);
133
  textdomain (PACKAGE);
134
 
135
  program_name = *argv;
136
  xmalloc_set_program_name (program_name);
137
 
138
  expandargv (&argc, &argv);
139
 
140
  bfd_init ();
141
  set_default_bfd_target ();
142
 
143
  while ((c = getopt_long (argc, argv, "ABHhVvdfotx", long_options,
144
                           (int *) 0)) != EOF)
145
    switch (c)
146
      {
147
      case OPTION_FORMAT:
148
        switch (*optarg)
149
          {
150
          case 'B':
151
          case 'b':
152
            berkeley_format = 1;
153
            break;
154
          case 'S':
155
          case 's':
156
            berkeley_format = 0;
157
            break;
158
          default:
159
            non_fatal (_("invalid argument to --format: %s"), optarg);
160
            usage (stderr, 1);
161
          }
162
        break;
163
 
164
      case OPTION_TARGET:
165
        target = optarg;
166
        break;
167
 
168
      case OPTION_RADIX:
169
#ifdef ANSI_LIBRARIES
170
        temp = strtol (optarg, NULL, 10);
171
#else
172
        temp = atol (optarg);
173
#endif
174
        switch (temp)
175
          {
176
          case 10:
177
            radix = decimal;
178
            break;
179
          case 8:
180
            radix = octal;
181
            break;
182
          case 16:
183
            radix = hex;
184
            break;
185
          default:
186
            non_fatal (_("Invalid radix: %s\n"), optarg);
187
            usage (stderr, 1);
188
          }
189
        break;
190
 
191
      case 'A':
192
        berkeley_format = 0;
193
        break;
194
      case 'B':
195
        berkeley_format = 1;
196
        break;
197
      case 'v':
198
      case 'V':
199
        show_version = 1;
200
        break;
201
      case 'd':
202
        radix = decimal;
203
        break;
204
      case 'x':
205
        radix = hex;
206
        break;
207
      case 'o':
208
        radix = octal;
209
        break;
210
      case 't':
211
        show_totals = 1;
212
        break;
213
      case 'f': /* FIXME : For sysv68, `-f' means `full format', i.e.
214
                   `[fname:] M(.text) + N(.data) + O(.bss) + P(.comment) = Q'
215
                   where `fname: ' appears only if there are >= 2 input files,
216
                   and M, N, O, P, Q are expressed in decimal by default,
217
                   hexa or octal if requested by `-x' or `-o'.
218
                   Just to make things interesting, Solaris also accepts -f,
219
                   which prints out the size of each allocatable section, the
220
                   name of the section, and the total of the section sizes.  */
221
                /* For the moment, accept `-f' silently, and ignore it.  */
222
        break;
223
      case 0:
224
        break;
225
      case 'h':
226
      case 'H':
227
      case '?':
228
        usage (stderr, 1);
229
      }
230
 
231
  if (show_version)
232
    print_version ("size");
233
  if (show_help)
234
    usage (stdout, 0);
235
 
236
  if (optind == argc)
237
    display_file ("a.out");
238
  else
239
    for (; optind < argc;)
240
      display_file (argv[optind++]);
241
 
242
  if (show_totals && berkeley_format)
243
    {
244
      bfd_size_type total = total_textsize + total_datasize + total_bsssize;
245
 
246
      rprint_number (7, total_textsize);
247
      putchar('\t');
248
      rprint_number (7, total_datasize);
249
      putchar('\t');
250
      rprint_number (7, total_bsssize);
251
      printf (((radix == octal) ? "\t%7lo\t%7lx\t" : "\t%7lu\t%7lx\t"),
252
              (unsigned long) total, (unsigned long) total);
253
      fputs ("(TOTALS)\n", stdout);
254
    }
255
 
256
  return return_code;
257
}
258
 
259
/* Total size required for common symbols in ABFD.  */
260
 
261
static void
262
calculate_common_size (bfd *abfd)
263
{
264
  asymbol **syms = NULL;
265
  long storage, symcount;
266
 
267
  common_size = 0;
268
  if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC | HAS_SYMS)) != HAS_SYMS)
269
    return;
270
 
271
  storage = bfd_get_symtab_upper_bound (abfd);
272
  if (storage < 0)
273
    bfd_fatal (bfd_get_filename (abfd));
274
  if (storage)
275
    syms = xmalloc (storage);
276
 
277
  symcount = bfd_canonicalize_symtab (abfd, syms);
278
  if (symcount < 0)
279
    bfd_fatal (bfd_get_filename (abfd));
280
 
281
  while (--symcount >= 0)
282
    {
283
      asymbol *sym = syms[symcount];
284
 
285
      if (bfd_is_com_section (sym->section)
286
          && (sym->flags & BSF_SECTION_SYM) == 0)
287
        common_size += sym->value;
288
    }
289
  free (syms);
290
}
291
 
292
/* Display stats on file or archive member ABFD.  */
293
 
294
static void
295
display_bfd (bfd *abfd)
296
{
297
  char **matching;
298
 
299
  if (bfd_check_format (abfd, bfd_archive))
300
    /* An archive within an archive.  */
301
    return;
302
 
303
  if (bfd_check_format_matches (abfd, bfd_object, &matching))
304
    {
305
      print_sizes (abfd);
306
      printf ("\n");
307
      return;
308
    }
309
 
310
  if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
311
    {
312
      bfd_nonfatal (bfd_get_filename (abfd));
313
      list_matching_formats (matching);
314
      free (matching);
315
      return_code = 3;
316
      return;
317
    }
318
 
319
  if (bfd_check_format_matches (abfd, bfd_core, &matching))
320
    {
321
      const char *core_cmd;
322
 
323
      print_sizes (abfd);
324
      fputs (" (core file", stdout);
325
 
326
      core_cmd = bfd_core_file_failing_command (abfd);
327
      if (core_cmd)
328
        printf (" invoked as %s", core_cmd);
329
 
330
      puts (")\n");
331
      return;
332
    }
333
 
334
  bfd_nonfatal (bfd_get_filename (abfd));
335
 
336
  if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
337
    {
338
      list_matching_formats (matching);
339
      free (matching);
340
    }
341
 
342
  return_code = 3;
343
}
344
 
345
static void
346
display_archive (bfd *file)
347
{
348
  bfd *arfile = (bfd *) NULL;
349
  bfd *last_arfile = (bfd *) NULL;
350
 
351
  for (;;)
352
    {
353
      bfd_set_error (bfd_error_no_error);
354
 
355
      arfile = bfd_openr_next_archived_file (file, arfile);
356
      if (arfile == NULL)
357
        {
358
          if (bfd_get_error () != bfd_error_no_more_archived_files)
359
            {
360
              bfd_nonfatal (bfd_get_filename (file));
361
              return_code = 2;
362
            }
363
          break;
364
        }
365
 
366
      display_bfd (arfile);
367
 
368
      if (last_arfile != NULL)
369
        bfd_close (last_arfile);
370
      last_arfile = arfile;
371
    }
372
 
373
  if (last_arfile != NULL)
374
    bfd_close (last_arfile);
375
}
376
 
377
static void
378
display_file (char *filename)
379
{
380
  bfd *file;
381
 
382
  if (get_file_size (filename) < 1)
383
    {
384
      return_code = 1;
385
      return;
386
    }
387
 
388
  file = bfd_openr (filename, target);
389
  if (file == NULL)
390
    {
391
      bfd_nonfatal (filename);
392
      return_code = 1;
393
      return;
394
    }
395
 
396
  if (bfd_check_format (file, bfd_archive))
397
    display_archive (file);
398
  else
399
    display_bfd (file);
400
 
401
  if (!bfd_close (file))
402
    {
403
      bfd_nonfatal (filename);
404
      return_code = 1;
405
      return;
406
    }
407
}
408
 
409
/* This is what lexical functions are for.  */
410
 
411
static int
412
size_number (bfd_size_type num)
413
{
414
  char buffer[40];
415
 
416
  sprintf (buffer,
417
           (radix == decimal ? "%lu" :
418
           ((radix == octal) ? "0%lo" : "0x%lx")),
419
           (unsigned long) num);
420
 
421
  return strlen (buffer);
422
}
423
 
424
static void
425
rprint_number (int width, bfd_size_type num)
426
{
427
  char buffer[40];
428
 
429
  sprintf (buffer,
430
           (radix == decimal ? "%lu" :
431
           ((radix == octal) ? "0%lo" : "0x%lx")),
432
           (unsigned long) num);
433
 
434
  printf ("%*s", width, buffer);
435
}
436
 
437
static bfd_size_type bsssize;
438
static bfd_size_type datasize;
439
static bfd_size_type textsize;
440
 
441
static void
442
berkeley_sum (bfd *abfd ATTRIBUTE_UNUSED, sec_ptr sec,
443
              void *ignore ATTRIBUTE_UNUSED)
444
{
445
  flagword flags;
446
  bfd_size_type size;
447
 
448
  flags = bfd_get_section_flags (abfd, sec);
449
  if ((flags & SEC_ALLOC) == 0)
450
    return;
451
 
452
  size = bfd_get_section_size (sec);
453
  if ((flags & SEC_CODE) != 0 || (flags & SEC_READONLY) != 0)
454
    textsize += size;
455
  else if ((flags & SEC_HAS_CONTENTS) != 0)
456
    datasize += size;
457
  else
458
    bsssize += size;
459
}
460
 
461
static void
462
print_berkeley_format (bfd *abfd)
463
{
464
  static int files_seen = 0;
465
  bfd_size_type total;
466
 
467
  bsssize = 0;
468
  datasize = 0;
469
  textsize = 0;
470
 
471
  bfd_map_over_sections (abfd, berkeley_sum, NULL);
472
 
473
  bsssize += common_size;
474
  if (files_seen++ == 0)
475
    puts ((radix == octal) ? "   text\t   data\t    bss\t    oct\t    hex\tfilename" :
476
          "   text\t   data\t    bss\t    dec\t    hex\tfilename");
477
 
478
  total = textsize + datasize + bsssize;
479
 
480
  if (show_totals)
481
    {
482
      total_textsize += textsize;
483
      total_datasize += datasize;
484
      total_bsssize  += bsssize;
485
    }
486
 
487
  rprint_number (7, textsize);
488
  putchar ('\t');
489
  rprint_number (7, datasize);
490
  putchar ('\t');
491
  rprint_number (7, bsssize);
492
  printf (((radix == octal) ? "\t%7lo\t%7lx\t" : "\t%7lu\t%7lx\t"),
493
          (unsigned long) total, (unsigned long) total);
494
 
495
  fputs (bfd_get_filename (abfd), stdout);
496
 
497
  if (bfd_my_archive (abfd))
498
    printf (" (ex %s)", bfd_get_filename (bfd_my_archive (abfd)));
499
}
500
 
501
/* I REALLY miss lexical functions! */
502
bfd_size_type svi_total = 0;
503
bfd_vma svi_maxvma = 0;
504
int svi_namelen = 0;
505
int svi_vmalen = 0;
506
int svi_sizelen = 0;
507
 
508
static void
509
sysv_internal_sizer (bfd *file ATTRIBUTE_UNUSED, sec_ptr sec,
510
                     void *ignore ATTRIBUTE_UNUSED)
511
{
512
  bfd_size_type size = bfd_section_size (file, sec);
513
 
514
  if (   ! bfd_is_abs_section (sec)
515
      && ! bfd_is_com_section (sec)
516
      && ! bfd_is_und_section (sec))
517
    {
518
      int namelen = strlen (bfd_section_name (file, sec));
519
 
520
      if (namelen > svi_namelen)
521
        svi_namelen = namelen;
522
 
523
      svi_total += size;
524
 
525
      if (bfd_section_vma (file, sec) > svi_maxvma)
526
        svi_maxvma = bfd_section_vma (file, sec);
527
    }
528
}
529
 
530
static void
531
sysv_one_line (const char *name, bfd_size_type size, bfd_vma vma)
532
{
533
  printf ("%-*s   ", svi_namelen, name);
534
  rprint_number (svi_sizelen, size);
535
  printf ("   ");
536
  rprint_number (svi_vmalen, vma);
537
  printf ("\n");
538
}
539
 
540
static void
541
sysv_internal_printer (bfd *file ATTRIBUTE_UNUSED, sec_ptr sec,
542
                       void *ignore ATTRIBUTE_UNUSED)
543
{
544
  bfd_size_type size = bfd_section_size (file, sec);
545
 
546
  if (   ! bfd_is_abs_section (sec)
547
      && ! bfd_is_com_section (sec)
548
      && ! bfd_is_und_section (sec))
549
    {
550
      svi_total += size;
551
 
552
      sysv_one_line (bfd_section_name (file, sec),
553
                     size,
554
                     bfd_section_vma (file, sec));
555
    }
556
}
557
 
558
static void
559
print_sysv_format (bfd *file)
560
{
561
  /* Size all of the columns.  */
562
  svi_total = 0;
563
  svi_maxvma = 0;
564
  svi_namelen = 0;
565
  bfd_map_over_sections (file, sysv_internal_sizer, NULL);
566
  if (show_common)
567
    {
568
      if (svi_namelen < (int) sizeof ("*COM*") - 1)
569
        svi_namelen = sizeof ("*COM*") - 1;
570
      svi_total += common_size;
571
    }
572
 
573
  svi_vmalen = size_number ((bfd_size_type)svi_maxvma);
574
 
575
  if ((size_t) svi_vmalen < sizeof ("addr") - 1)
576
    svi_vmalen = sizeof ("addr")-1;
577
 
578
  svi_sizelen = size_number (svi_total);
579
  if ((size_t) svi_sizelen < sizeof ("size") - 1)
580
    svi_sizelen = sizeof ("size")-1;
581
 
582
  svi_total = 0;
583
  printf ("%s  ", bfd_get_filename (file));
584
 
585
  if (bfd_my_archive (file))
586
    printf (" (ex %s)", bfd_get_filename (bfd_my_archive (file)));
587
 
588
  printf (":\n%-*s   %*s   %*s\n", svi_namelen, "section",
589
          svi_sizelen, "size", svi_vmalen, "addr");
590
 
591
  bfd_map_over_sections (file, sysv_internal_printer, NULL);
592
  if (show_common)
593
    {
594
      svi_total += common_size;
595
      sysv_one_line ("*COM*", common_size, 0);
596
    }
597
 
598
  printf ("%-*s   ", svi_namelen, "Total");
599
  rprint_number (svi_sizelen, svi_total);
600
  printf ("\n\n");
601
}
602
 
603
static void
604
print_sizes (bfd *file)
605
{
606
  if (show_common)
607
    calculate_common_size (file);
608
  if (berkeley_format)
609
    print_berkeley_format (file);
610
  else
611
    print_sysv_format (file);
612
}

powered by: WebSVN 2.1.0

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