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