* config/obj-coff.c (coff_adjust_section_syms): Use
[deliverable/binutils-gdb.git] / binutils / size.c
CommitLineData
252b5132 1/* size.c -- report size of various sections of an executable file.
b34976b6 2 Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2da42df6 3 2002, 2003 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
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
252b5132
RH
48int berkeley_format = BSD_DEFAULT; /* 0 means use AT&T-style output. */
49int show_version = 0;
50int show_help = 0;
15c82623
NC
51int show_totals = 0;
52
53static bfd_size_type total_bsssize;
54static bfd_size_type total_datasize;
55static bfd_size_type total_textsize;
252b5132
RH
56
57/* Program exit status. */
58int return_code = 0;
59
60static char *target = NULL;
61
15c82623 62/* Static declarations. */
252b5132 63
2da42df6
AJ
64static void usage (FILE *, int);
65static void display_file (char *);
66static void display_bfd (bfd *);
67static void display_archive (bfd *);
68static int size_number (bfd_size_type);
252b5132 69#if 0
2da42df6 70static void lprint_number (int, bfd_size_type);
252b5132 71#endif
2da42df6
AJ
72static void rprint_number (int, bfd_size_type);
73static void print_berkeley_format (bfd *);
74static void sysv_internal_sizer (bfd *, asection *, void *);
75static void sysv_internal_printer (bfd *, asection *, void *);
76static void print_sysv_format (bfd *);
77static void print_sizes (bfd * file);
78static void berkeley_sum (bfd *, sec_ptr, void *);
252b5132
RH
79\f
80static void
2da42df6 81usage (FILE *stream, int status)
252b5132 82{
8b53311e
NC
83 fprintf (stream, _("Usage: %s [option(s)] [file(s)]\n"), program_name);
84 fprintf (stream, _(" Displays the sizes of sections inside binary files\n"));
9f66665a 85 fprintf (stream, _(" If no input file(s) are specified, a.out is assumed\n"));
8b53311e
NC
86 fprintf (stream, _(" The options are:\n\
87 -A|-B --format={sysv|berkeley} Select output style (default is %s)\n\
92acdfaf 88 -o|-d|-x --radix={8|10|16} Display numbers in octal, decimal or hex\n\
15c82623 89 -t --totals Display the total sizes (Berkeley only)\n\
8b53311e
NC
90 --target=<bfdname> Set the binary file format\n\
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
106struct option long_options[] =
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
137 bfd_init ();
138 set_default_bfd_target ();
139
15c82623 140 while ((c = getopt_long (argc, argv, "ABHhVvdfotx", long_options,
252b5132
RH
141 (int *) 0)) != EOF)
142 switch (c)
143 {
144 case 200: /* --format */
145 switch (*optarg)
146 {
147 case 'B':
148 case 'b':
149 berkeley_format = 1;
150 break;
151 case 'S':
152 case 's':
153 berkeley_format = 0;
154 break;
155 default:
37cc8ec1 156 non_fatal (_("invalid argument to --format: %s"), optarg);
252b5132
RH
157 usage (stderr, 1);
158 }
159 break;
160
161 case 202: /* --target */
162 target = optarg;
163 break;
164
165 case 201: /* --radix */
166#ifdef ANSI_LIBRARIES
167 temp = strtol (optarg, NULL, 10);
168#else
169 temp = atol (optarg);
170#endif
171 switch (temp)
172 {
173 case 10:
174 radix = decimal;
175 break;
176 case 8:
177 radix = octal;
178 break;
179 case 16:
180 radix = hex;
181 break;
182 default:
37cc8ec1 183 non_fatal (_("Invalid radix: %s\n"), optarg);
252b5132
RH
184 usage (stderr, 1);
185 }
186 break;
187
188 case 'A':
189 berkeley_format = 0;
190 break;
191 case 'B':
192 berkeley_format = 1;
193 break;
8b53311e 194 case 'v':
252b5132
RH
195 case 'V':
196 show_version = 1;
197 break;
198 case 'd':
199 radix = decimal;
200 break;
201 case 'x':
202 radix = hex;
203 break;
204 case 'o':
205 radix = octal;
206 break;
15c82623
NC
207 case 't':
208 show_totals = 1;
209 break;
e3a69612
AM
210 case 'f': /* FIXME : For sysv68, `-f' means `full format', i.e.
211 `[fname:] M(.text) + N(.data) + O(.bss) + P(.comment) = Q'
212 where `fname: ' appears only if there are >= 2 input files,
213 and M, N, O, P, Q are expressed in decimal by default,
214 hexa or octal if requested by `-x' or `-o'.
215 Just to make things interesting, Solaris also accepts -f,
216 which prints out the size of each allocatable section, the
217 name of the section, and the total of the section sizes. */
218 /* For the moment, accept `-f' silently, and ignore it. */
219 break;
252b5132
RH
220 case 0:
221 break;
8b53311e
NC
222 case 'h':
223 case 'H':
252b5132
RH
224 case '?':
225 usage (stderr, 1);
226 }
227
228 if (show_version)
229 print_version ("size");
230 if (show_help)
231 usage (stdout, 0);
232
233 if (optind == argc)
234 display_file ("a.out");
235 else
236 for (; optind < argc;)
237 display_file (argv[optind++]);
238
15c82623
NC
239 if (show_totals && berkeley_format)
240 {
241 bfd_size_type total = total_textsize + total_datasize + total_bsssize;
242
243 rprint_number (7, total_textsize);
244 putchar('\t');
245 rprint_number (7, total_datasize);
246 putchar('\t');
247 rprint_number (7, total_bsssize);
248 printf (((radix == octal) ? "\t%7lo\t%7lx\t" : "\t%7lu\t%7lx\t"),
249 (unsigned long) total, (unsigned long) total);
250 fputs ("(TOTALS)\n", stdout);
251 }
252
252b5132
RH
253 return return_code;
254}
255\f
256/* Display stats on file or archive member ABFD. */
257
258static void
2da42df6 259display_bfd (bfd *abfd)
252b5132
RH
260{
261 char **matching;
262
263 if (bfd_check_format (abfd, bfd_archive))
264 /* An archive within an archive. */
265 return;
266
267 if (bfd_check_format_matches (abfd, bfd_object, &matching))
268 {
269 print_sizes (abfd);
270 printf ("\n");
271 return;
272 }
273
274 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
275 {
276 bfd_nonfatal (bfd_get_filename (abfd));
277 list_matching_formats (matching);
278 free (matching);
279 return_code = 3;
280 return;
281 }
282
283 if (bfd_check_format_matches (abfd, bfd_core, &matching))
284 {
15c82623 285 const char *core_cmd;
252b5132
RH
286
287 print_sizes (abfd);
288 fputs (" (core file", stdout);
289
290 core_cmd = bfd_core_file_failing_command (abfd);
291 if (core_cmd)
292 printf (" invoked as %s", core_cmd);
293
294 puts (")\n");
295 return;
296 }
297
298 bfd_nonfatal (bfd_get_filename (abfd));
299
300 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
301 {
302 list_matching_formats (matching);
303 free (matching);
304 }
305
306 return_code = 3;
307}
308
309static void
2da42df6 310display_archive (bfd *file)
252b5132
RH
311{
312 bfd *arfile = (bfd *) NULL;
6b52b824 313 bfd *last_arfile = (bfd *) NULL;
252b5132
RH
314
315 for (;;)
316 {
317 bfd_set_error (bfd_error_no_error);
318
319 arfile = bfd_openr_next_archived_file (file, arfile);
320 if (arfile == NULL)
321 {
322 if (bfd_get_error () != bfd_error_no_more_archived_files)
323 {
324 bfd_nonfatal (bfd_get_filename (file));
325 return_code = 2;
326 }
327 break;
328 }
329
330 display_bfd (arfile);
6b52b824
AM
331
332 if (last_arfile != NULL)
333 bfd_close (last_arfile);
334 last_arfile = arfile;
252b5132 335 }
6b52b824
AM
336
337 if (last_arfile != NULL)
338 bfd_close (last_arfile);
252b5132
RH
339}
340
341static void
2da42df6 342display_file (char *filename)
252b5132 343{
f24ddbdd 344 bfd *file;
15c82623 345
f24ddbdd
NC
346 if (get_file_size (filename) < 1)
347 return;
348
349 file = bfd_openr (filename, target);
252b5132
RH
350 if (file == NULL)
351 {
352 bfd_nonfatal (filename);
353 return_code = 1;
354 return;
355 }
356
b34976b6 357 if (bfd_check_format (file, bfd_archive))
252b5132
RH
358 display_archive (file);
359 else
360 display_bfd (file);
361
b34976b6 362 if (!bfd_close (file))
252b5132
RH
363 {
364 bfd_nonfatal (filename);
365 return_code = 1;
366 return;
367 }
368}
369\f
370/* This is what lexical functions are for. */
371
372static int
2da42df6 373size_number (bfd_size_type num)
252b5132
RH
374{
375 char buffer[40];
15c82623 376
252b5132
RH
377 sprintf (buffer,
378 (radix == decimal ? "%lu" :
379 ((radix == octal) ? "0%lo" : "0x%lx")),
380 (unsigned long) num);
381
382 return strlen (buffer);
383}
384
385#if 0
386
387/* This is not used. */
388
389static void
2da42df6 390lprint_number (int width, bfd_size_type num)
252b5132
RH
391{
392 char buffer[40];
15c82623 393
252b5132
RH
394 sprintf (buffer,
395 (radix == decimal ? "%lu" :
396 ((radix == octal) ? "0%lo" : "0x%lx")),
397 (unsigned long) num);
398
399 printf ("%-*s", width, buffer);
400}
401
402#endif
403
404static void
2da42df6 405rprint_number (int width, bfd_size_type num)
252b5132
RH
406{
407 char buffer[40];
15c82623 408
252b5132
RH
409 sprintf (buffer,
410 (radix == decimal ? "%lu" :
411 ((radix == octal) ? "0%lo" : "0x%lx")),
412 (unsigned long) num);
413
414 printf ("%*s", width, buffer);
415}
416
417static bfd_size_type bsssize;
418static bfd_size_type datasize;
419static bfd_size_type textsize;
420
421static void
2da42df6
AJ
422berkeley_sum (bfd *abfd ATTRIBUTE_UNUSED, sec_ptr sec,
423 void *ignore ATTRIBUTE_UNUSED)
252b5132
RH
424{
425 flagword flags;
426 bfd_size_type size;
427
428 flags = bfd_get_section_flags (abfd, sec);
429 if ((flags & SEC_ALLOC) == 0)
430 return;
431
432 size = bfd_get_section_size_before_reloc (sec);
433 if ((flags & SEC_CODE) != 0 || (flags & SEC_READONLY) != 0)
434 textsize += size;
435 else if ((flags & SEC_HAS_CONTENTS) != 0)
436 datasize += size;
437 else
438 bsssize += size;
439}
440
9f66665a 441static void
2da42df6 442print_berkeley_format (bfd *abfd)
252b5132
RH
443{
444 static int files_seen = 0;
445 bfd_size_type total;
446
447 bsssize = 0;
448 datasize = 0;
449 textsize = 0;
450
2da42df6 451 bfd_map_over_sections (abfd, berkeley_sum, NULL);
252b5132
RH
452
453 if (files_seen++ == 0)
454#if 0
455 /* Intel doesn't like bss/stk because they don't have core files. */
456 puts ((radix == octal) ? " text\t data\tbss/stk\t oct\t hex\tfilename" :
457 " text\t data\tbss/stk\t dec\t hex\tfilename");
458#else
459 puts ((radix == octal) ? " text\t data\t bss\t oct\t hex\tfilename" :
460 " text\t data\t bss\t dec\t hex\tfilename");
461#endif
462
463 total = textsize + datasize + bsssize;
464
15c82623
NC
465 if (show_totals)
466 {
467 total_textsize += textsize;
468 total_datasize += datasize;
469 total_bsssize += bsssize;
470 }
471
252b5132
RH
472 rprint_number (7, textsize);
473 putchar ('\t');
474 rprint_number (7, datasize);
475 putchar ('\t');
476 rprint_number (7, bsssize);
477 printf (((radix == octal) ? "\t%7lo\t%7lx\t" : "\t%7lu\t%7lx\t"),
478 (unsigned long) total, (unsigned long) total);
479
480 fputs (bfd_get_filename (abfd), stdout);
15c82623 481
252b5132
RH
482 if (bfd_my_archive (abfd))
483 printf (" (ex %s)", bfd_get_filename (bfd_my_archive (abfd)));
484}
485
486/* I REALLY miss lexical functions! */
487bfd_size_type svi_total = 0;
488bfd_vma svi_maxvma = 0;
489int svi_namelen = 0;
490int svi_vmalen = 0;
491int svi_sizelen = 0;
492
493static void
2da42df6
AJ
494sysv_internal_sizer (bfd *file ATTRIBUTE_UNUSED, sec_ptr sec,
495 void *ignore ATTRIBUTE_UNUSED)
252b5132
RH
496{
497 bfd_size_type size = bfd_section_size (file, sec);
15c82623
NC
498
499 if ( ! bfd_is_abs_section (sec)
500 && ! bfd_is_com_section (sec)
501 && ! bfd_is_und_section (sec))
252b5132
RH
502 {
503 int namelen = strlen (bfd_section_name (file, sec));
15c82623 504
252b5132
RH
505 if (namelen > svi_namelen)
506 svi_namelen = namelen;
507
508 svi_total += size;
15c82623 509
252b5132
RH
510 if (bfd_section_vma (file, sec) > svi_maxvma)
511 svi_maxvma = bfd_section_vma (file, sec);
512 }
513}
514
515static void
2da42df6
AJ
516sysv_internal_printer (bfd *file ATTRIBUTE_UNUSED, sec_ptr sec,
517 void *ignore ATTRIBUTE_UNUSED)
252b5132
RH
518{
519 bfd_size_type size = bfd_section_size (file, sec);
15c82623
NC
520
521 if ( ! bfd_is_abs_section (sec)
522 && ! bfd_is_com_section (sec)
523 && ! bfd_is_und_section (sec))
252b5132
RH
524 {
525 svi_total += size;
526
527 printf ("%-*s ", svi_namelen, bfd_section_name (file, sec));
528 rprint_number (svi_sizelen, size);
529 printf (" ");
530 rprint_number (svi_vmalen, bfd_section_vma (file, sec));
531 printf ("\n");
532 }
533}
534
535static void
2da42df6 536print_sysv_format (bfd *file)
252b5132 537{
15c82623 538 /* Size all of the columns. */
252b5132
RH
539 svi_total = 0;
540 svi_maxvma = 0;
541 svi_namelen = 0;
2da42df6 542 bfd_map_over_sections (file, sysv_internal_sizer, NULL);
252b5132 543 svi_vmalen = size_number ((bfd_size_type)svi_maxvma);
15c82623 544
252b5132
RH
545 if ((size_t) svi_vmalen < sizeof ("addr") - 1)
546 svi_vmalen = sizeof ("addr")-1;
547
548 svi_sizelen = size_number (svi_total);
549 if ((size_t) svi_sizelen < sizeof ("size") - 1)
550 svi_sizelen = sizeof ("size")-1;
551
552 svi_total = 0;
553 printf ("%s ", bfd_get_filename (file));
15c82623 554
252b5132
RH
555 if (bfd_my_archive (file))
556 printf (" (ex %s)", bfd_get_filename (bfd_my_archive (file)));
557
558 printf (":\n%-*s %*s %*s\n", svi_namelen, "section",
559 svi_sizelen, "size", svi_vmalen, "addr");
15c82623 560
2da42df6 561 bfd_map_over_sections (file, sysv_internal_printer, NULL);
252b5132
RH
562
563 printf ("%-*s ", svi_namelen, "Total");
564 rprint_number (svi_sizelen, svi_total);
565 printf ("\n\n");
566}
567
568static void
2da42df6 569print_sizes (bfd *file)
252b5132
RH
570{
571 if (berkeley_format)
572 print_berkeley_format (file);
573 else
574 print_sysv_format (file);
575}
This page took 0.416166 seconds and 4 git commands to generate.