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