Revert the value change of DT_ENCODING from 2003-01-17. Luckily (and
[deliverable/binutils-gdb.git] / binutils / size.c
CommitLineData
252b5132 1/* size.c -- report size of various sections of an executable file.
aef6203b 2 Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
92f01d61 3 2001, 2002, 2003, 2004, 2005, 2006, 2007 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 100 list_supported_targets (program_name, stream);
92f01d61 101 if (REPORT_BUGS_TO[0] && 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 348 if (get_file_size (filename) < 1)
d68c385b
NC
349 {
350 return_code = 1;
351 return;
352 }
f24ddbdd
NC
353
354 file = bfd_openr (filename, target);
252b5132
RH
355 if (file == NULL)
356 {
357 bfd_nonfatal (filename);
358 return_code = 1;
359 return;
360 }
361
b34976b6 362 if (bfd_check_format (file, bfd_archive))
252b5132
RH
363 display_archive (file);
364 else
365 display_bfd (file);
366
b34976b6 367 if (!bfd_close (file))
252b5132
RH
368 {
369 bfd_nonfatal (filename);
370 return_code = 1;
371 return;
372 }
373}
374\f
375/* This is what lexical functions are for. */
376
377static int
2da42df6 378size_number (bfd_size_type num)
252b5132
RH
379{
380 char buffer[40];
15c82623 381
252b5132
RH
382 sprintf (buffer,
383 (radix == decimal ? "%lu" :
384 ((radix == octal) ? "0%lo" : "0x%lx")),
385 (unsigned long) num);
386
387 return strlen (buffer);
388}
389
252b5132 390static void
2da42df6 391rprint_number (int width, bfd_size_type num)
252b5132
RH
392{
393 char buffer[40];
15c82623 394
252b5132
RH
395 sprintf (buffer,
396 (radix == decimal ? "%lu" :
397 ((radix == octal) ? "0%lo" : "0x%lx")),
398 (unsigned long) num);
399
400 printf ("%*s", width, buffer);
401}
402
403static bfd_size_type bsssize;
404static bfd_size_type datasize;
405static bfd_size_type textsize;
406
407static void
2da42df6
AJ
408berkeley_sum (bfd *abfd ATTRIBUTE_UNUSED, sec_ptr sec,
409 void *ignore ATTRIBUTE_UNUSED)
252b5132
RH
410{
411 flagword flags;
412 bfd_size_type size;
413
414 flags = bfd_get_section_flags (abfd, sec);
415 if ((flags & SEC_ALLOC) == 0)
416 return;
417
135dfb4a 418 size = bfd_get_section_size (sec);
252b5132
RH
419 if ((flags & SEC_CODE) != 0 || (flags & SEC_READONLY) != 0)
420 textsize += size;
421 else if ((flags & SEC_HAS_CONTENTS) != 0)
422 datasize += size;
423 else
424 bsssize += size;
425}
426
9f66665a 427static void
2da42df6 428print_berkeley_format (bfd *abfd)
252b5132
RH
429{
430 static int files_seen = 0;
431 bfd_size_type total;
432
433 bsssize = 0;
434 datasize = 0;
435 textsize = 0;
436
2da42df6 437 bfd_map_over_sections (abfd, berkeley_sum, NULL);
252b5132
RH
438
439 if (files_seen++ == 0)
252b5132
RH
440 puts ((radix == octal) ? " text\t data\t bss\t oct\t hex\tfilename" :
441 " text\t data\t bss\t dec\t hex\tfilename");
252b5132
RH
442
443 total = textsize + datasize + bsssize;
444
15c82623
NC
445 if (show_totals)
446 {
447 total_textsize += textsize;
448 total_datasize += datasize;
449 total_bsssize += bsssize;
450 }
451
252b5132
RH
452 rprint_number (7, textsize);
453 putchar ('\t');
454 rprint_number (7, datasize);
455 putchar ('\t');
456 rprint_number (7, bsssize);
457 printf (((radix == octal) ? "\t%7lo\t%7lx\t" : "\t%7lu\t%7lx\t"),
458 (unsigned long) total, (unsigned long) total);
459
460 fputs (bfd_get_filename (abfd), stdout);
15c82623 461
252b5132
RH
462 if (bfd_my_archive (abfd))
463 printf (" (ex %s)", bfd_get_filename (bfd_my_archive (abfd)));
464}
465
466/* I REALLY miss lexical functions! */
467bfd_size_type svi_total = 0;
468bfd_vma svi_maxvma = 0;
469int svi_namelen = 0;
470int svi_vmalen = 0;
471int svi_sizelen = 0;
472
473static void
2da42df6
AJ
474sysv_internal_sizer (bfd *file ATTRIBUTE_UNUSED, sec_ptr sec,
475 void *ignore ATTRIBUTE_UNUSED)
252b5132
RH
476{
477 bfd_size_type size = bfd_section_size (file, sec);
15c82623
NC
478
479 if ( ! bfd_is_abs_section (sec)
480 && ! bfd_is_com_section (sec)
481 && ! bfd_is_und_section (sec))
252b5132
RH
482 {
483 int namelen = strlen (bfd_section_name (file, sec));
15c82623 484
252b5132
RH
485 if (namelen > svi_namelen)
486 svi_namelen = namelen;
487
488 svi_total += size;
15c82623 489
252b5132
RH
490 if (bfd_section_vma (file, sec) > svi_maxvma)
491 svi_maxvma = bfd_section_vma (file, sec);
492 }
493}
494
495static void
2da42df6
AJ
496sysv_internal_printer (bfd *file ATTRIBUTE_UNUSED, sec_ptr sec,
497 void *ignore ATTRIBUTE_UNUSED)
252b5132
RH
498{
499 bfd_size_type size = bfd_section_size (file, sec);
15c82623
NC
500
501 if ( ! bfd_is_abs_section (sec)
502 && ! bfd_is_com_section (sec)
503 && ! bfd_is_und_section (sec))
252b5132
RH
504 {
505 svi_total += size;
506
507 printf ("%-*s ", svi_namelen, bfd_section_name (file, sec));
508 rprint_number (svi_sizelen, size);
509 printf (" ");
510 rprint_number (svi_vmalen, bfd_section_vma (file, sec));
511 printf ("\n");
512 }
513}
514
515static void
2da42df6 516print_sysv_format (bfd *file)
252b5132 517{
15c82623 518 /* Size all of the columns. */
252b5132
RH
519 svi_total = 0;
520 svi_maxvma = 0;
521 svi_namelen = 0;
2da42df6 522 bfd_map_over_sections (file, sysv_internal_sizer, NULL);
252b5132 523 svi_vmalen = size_number ((bfd_size_type)svi_maxvma);
15c82623 524
252b5132
RH
525 if ((size_t) svi_vmalen < sizeof ("addr") - 1)
526 svi_vmalen = sizeof ("addr")-1;
527
528 svi_sizelen = size_number (svi_total);
529 if ((size_t) svi_sizelen < sizeof ("size") - 1)
530 svi_sizelen = sizeof ("size")-1;
531
532 svi_total = 0;
533 printf ("%s ", bfd_get_filename (file));
15c82623 534
252b5132
RH
535 if (bfd_my_archive (file))
536 printf (" (ex %s)", bfd_get_filename (bfd_my_archive (file)));
537
538 printf (":\n%-*s %*s %*s\n", svi_namelen, "section",
539 svi_sizelen, "size", svi_vmalen, "addr");
15c82623 540
2da42df6 541 bfd_map_over_sections (file, sysv_internal_printer, NULL);
252b5132
RH
542
543 printf ("%-*s ", svi_namelen, "Total");
544 rprint_number (svi_sizelen, svi_total);
545 printf ("\n\n");
546}
547
548static void
2da42df6 549print_sizes (bfd *file)
252b5132
RH
550{
551 if (berkeley_format)
552 print_berkeley_format (file);
553 else
554 print_sysv_format (file);
555}
This page took 0.323791 seconds and 4 git commands to generate.