home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / binutils-2.2.1 / binutils / size.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-29  |  8.4 KB  |  360 lines

  1. /* size.c -- report size of various sections of an executable file.
  2.    Copyright 1991, 1992 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Binutils.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  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
  29.    out of luck; there's no --predantic option.
  30. */
  31.  
  32. #include "bfd.h"
  33. #include "sysdep.h"
  34. #include "getopt.h"
  35.  
  36. #ifndef BSD_DEFAULT
  37. #define BSD_DEFAULT 1
  38. #endif
  39.  
  40. /* Various program options */
  41.  
  42. enum {decimal, octal, hex} radix = decimal;
  43. int berkeley_format = BSD_DEFAULT; /* 0 means use AT&T-style output */
  44. int show_version = 0;
  45. int show_help = 0;
  46.  
  47. int return_code = 0;
  48.  
  49. /* IMPORTS */
  50. extern char *program_version;
  51. extern char *program_name;
  52. extern char *target;
  53.  
  54. /* Forward declarations */
  55.  
  56. static void
  57. display_file PARAMS ((char *filename));
  58.  
  59. static void
  60. print_sizes PARAMS ((bfd *file));
  61.  
  62. /** main and like trivia */
  63.  
  64. void
  65. usage ()
  66. {
  67.   fprintf (stderr, "\
  68. Usage: %s [-ABdoxV] [--format=berkeley|sysv] [--radix=8|10|16]\n\
  69.        [--target=bfdname] [--version] [--help] [file...]\n", program_name);
  70. #if BSD_DEFAULT
  71.   fputs ("       (default is --format=berkeley)\n", stderr);
  72. #else
  73.   fputs ("       (default is --format=sysv)\n", stderr);
  74. #endif
  75.   exit (1);
  76. }
  77.  
  78. struct option long_options[] = {
  79.   {"format",  required_argument, 0, 200},
  80.   {"radix",   required_argument, 0, 201},
  81.   {"target",  required_argument, 0, 202},
  82.   {"version", no_argument, &show_version, 1},
  83.   {"help",    no_argument, &show_help, 1},
  84.   {0, no_argument, 0, 0}
  85. };
  86.  
  87. int
  88. main (argc, argv)
  89.      int argc;
  90.      char **argv;
  91. {
  92.   int temp;
  93.   int c;            /* sez which option char */
  94.   extern int optind;        /* steps thru options */
  95.  
  96.   program_name = *argv;
  97.  
  98.   bfd_init();
  99.  
  100.   while ((c = getopt_long(argc, argv, "ABVdox", long_options,
  101.               (int *) 0)) != EOF)
  102.     switch(c) {
  103.     case 200:            /* --format */
  104.     switch(*optarg) {
  105.     case 'B': case 'b': berkeley_format = 1; break;
  106.     case 'S': case 's': berkeley_format = 0; break;
  107.     default: fprintf(stderr, "invalid argument to --format: %s\n", optarg);
  108.       usage();
  109.     }
  110.     break;
  111.  
  112.       case 202:            /* --target */
  113.     target = optarg;
  114.     break;
  115.  
  116.       case 201:            /* --radix */
  117. #ifdef ANSI_LIBRARIES
  118.     temp = strtol(optarg, NULL, 10);
  119. #else
  120.     temp = atol(optarg);
  121. #endif
  122.     switch(temp) {
  123.     case 10: radix = decimal; break;
  124.     case 8:  radix = octal; break;
  125.     case 16: radix = hex; break;
  126.     default: printf("Unknown radix: %s\n", optarg);
  127.       usage();
  128.     }
  129.     break;
  130.  
  131.     case 'A': berkeley_format = 0; break;
  132.     case 'B': berkeley_format = 1; break;
  133.     case 'V': show_version = 1; break;
  134.     case 'd': radix = decimal; break;
  135.     case 'x': radix = hex; break;
  136.     case 'o': radix = octal; break;
  137.     case '?': usage();
  138.     }
  139.  
  140.   if (show_version) printf("%s version %s\n", program_name, program_version);
  141.   if (show_help) usage();
  142.     
  143.   if (optind == argc)
  144.     display_file ("a.out");
  145.   else
  146.     for (; optind < argc;)
  147.       display_file (argv[optind++]);
  148.  
  149.   return return_code;
  150. }
  151.  
  152. /** Display a file's stats */
  153.  
  154. void
  155. display_bfd (abfd)
  156.      bfd *abfd;
  157. {
  158.   CONST  char *core_cmd;
  159.  
  160.   if (bfd_check_format(abfd, bfd_archive)) return;
  161.  
  162.   if (bfd_check_format(abfd, bfd_object)) {
  163.     print_sizes(abfd);
  164.     goto done;
  165.   }
  166.  
  167.   if (bfd_check_format(abfd, bfd_core)) {
  168.     print_sizes(abfd);
  169.     fputs(" (core file", stdout);
  170.  
  171.     core_cmd = bfd_core_file_failing_command(abfd);
  172.     if (core_cmd) printf(" invoked as %s", core_cmd);
  173.  
  174.     puts(")");
  175.     goto done;
  176.   }
  177.   
  178.   printf("Unknown file format: %s.", bfd_get_filename(abfd));
  179.   return_code = 3;
  180.  
  181.  done:
  182.  
  183.  
  184.   printf("\n");
  185.   return;
  186. }
  187.  
  188. static void
  189. display_file(filename)
  190.      char *filename;
  191. {
  192.   bfd *file, *arfile = (bfd *) NULL;
  193.  
  194.   file = bfd_openr (filename, target);
  195.   if (file == NULL) {
  196.     fprintf (stderr, "%s: ", program_name);
  197.     bfd_perror (filename);
  198.     return_code = 1;
  199.     return;
  200.   }
  201.  
  202.   if (bfd_check_format(file, bfd_archive) == true) {
  203.     for(;;) {
  204.       
  205.       bfd_error = no_error;
  206.  
  207.        arfile = bfd_openr_next_archived_file (file, arfile);
  208.       if (arfile == NULL) {
  209.     if (bfd_error != no_more_archived_files) {
  210.       fprintf (stderr, "%s: ", program_name);
  211.       bfd_perror (bfd_get_filename (file));
  212.       return_code = 2;
  213.         }
  214.     return;
  215.       }
  216.  
  217.       display_bfd (arfile);
  218.       /* Don't close the archive elements; we need them for next_archive */
  219.     }
  220.   }
  221.   else
  222.     display_bfd (file);
  223.  
  224.   bfd_close (file);
  225. }
  226.  
  227. /* This is what lexical functions are for */
  228. void
  229. lprint_number (width, num)
  230.      int width;
  231.      bfd_size_type num;
  232. {
  233.   printf ((radix == decimal ? "%-*lu\t" :
  234.        ((radix == octal) ? "%-*lo\t" : "%-*lx\t")),
  235.       width, (unsigned long)num);
  236. }
  237.  
  238. void
  239. rprint_number(width, num)
  240.      int width;
  241.      bfd_size_type num;
  242. {
  243.   printf ((radix == decimal ? "%*lu\t" :
  244.        ((radix == octal) ? "%*lo\t" : "%*lx\t")),
  245.       width, (unsigned long)num);
  246. }
  247.  
  248. static char *bss_section_name = ".bss";
  249. static char *data_section_name = ".data";
  250. static char *stack_section_name = ".stack";
  251. static char *text_section_name = ".text";
  252.  
  253. void print_berkeley_format(abfd)
  254. bfd *abfd;
  255. {
  256.   static int files_seen = 0;
  257.   sec_ptr bsssection = NULL;
  258.   sec_ptr datasection = NULL;
  259.   sec_ptr textsection = NULL;
  260.   bfd_size_type bsssize = 0;
  261.   bfd_size_type datasize = 0;
  262.   bfd_size_type textsize = 0;
  263.   bfd_size_type total = 0;
  264.  
  265.   
  266.   if ((textsection = bfd_get_section_by_name (abfd, text_section_name))
  267.       != NULL) {
  268.     textsize = bfd_get_section_size_before_reloc (textsection);
  269.   }
  270.  
  271.   if ((datasection = bfd_get_section_by_name (abfd, data_section_name))
  272.       != NULL) {
  273.     datasize = bfd_get_section_size_before_reloc ( datasection);
  274.   }
  275.     
  276.   if (bfd_get_format (abfd) == bfd_object) {
  277.     if ((bsssection = bfd_get_section_by_name (abfd, bss_section_name))
  278.     != NULL) {
  279.       bsssize = bfd_section_size(abfd, bsssection);
  280.     }
  281.   } else {
  282.     if ((bsssection = bfd_get_section_by_name (abfd, stack_section_name))
  283.     != NULL) {
  284.       bsssize = bfd_section_size(abfd, bsssection);
  285.     }
  286.   }
  287.  
  288.   if (files_seen++ == 0)
  289. #if 0    /* intel doesn't like bss/stk b/c they don't gave core files */
  290.     puts((radix == octal) ? "text\tdata\tbss/stk\toct\thex\tfilename" :
  291.      "text\tdata\tbss/stk\tdec\thex\tfilename");
  292. #else
  293.     puts((radix == octal) ? "text\tdata\tbss\toct\thex\tfilename" :
  294.      "text\tdata\tbss\tdec\thex\tfilename");
  295. #endif
  296.     
  297.   total = textsize + datasize + bsssize;
  298.     
  299.   lprint_number (7, textsize);
  300.   lprint_number (7, datasize);
  301.   lprint_number (7, bsssize);
  302.   printf (((radix == octal) ? "%-7lo\t%-7lx\t" : "%-7lu\t%-7lx\t"),
  303.       (unsigned long)total, (unsigned long)total);
  304.  
  305.   fputs(bfd_get_filename(abfd), stdout);
  306.   if (abfd->my_archive) printf (" (ex %s)", abfd->my_archive->filename);
  307. }
  308.  
  309. /* I REALLY miss lexical functions! */
  310. bfd_size_type svi_total = 0;
  311.  
  312. void
  313. sysv_internal_printer(file, sec, ignore)
  314.      bfd *file;
  315.      sec_ptr sec;
  316.      PTR ignore;
  317. {
  318.   bfd_size_type size = bfd_section_size (file, sec);
  319.   if (sec!= &bfd_abs_section 
  320.       && ! bfd_is_com_section (sec)
  321.       && sec!=&bfd_und_section) 
  322.   {
  323.   
  324.     svi_total += size;
  325.     
  326.     printf ("%-12s", bfd_section_name(file, sec));
  327.     rprint_number (8, size);
  328.     printf(" ");
  329.     rprint_number (8, bfd_section_vma(file, sec));
  330.     printf ("\n");
  331.   }
  332.  
  333. }
  334.  
  335. void
  336. print_sysv_format(file)
  337.      bfd *file;
  338. {
  339.   svi_total = 0;
  340.  
  341.   printf ("%s  ", bfd_get_filename (file));
  342.   if (file->my_archive) printf (" (ex %s)", file->my_archive->filename);
  343.  
  344.   puts(":\nsection\t\tsize\t     addr");
  345.   bfd_map_over_sections (file, sysv_internal_printer, (PTR)NULL);
  346.  
  347.   printf("Total       ");
  348.   rprint_number(8, svi_total);
  349.   printf("\n");  printf("\n");
  350. }
  351.  
  352. static void
  353. print_sizes(file)
  354.      bfd *file;
  355. {
  356.   if (berkeley_format)
  357.     print_berkeley_format(file);
  358.   else print_sysv_format(file);
  359. }
  360.