@ -1,5 +1,5 @@
/* size.c -- report size of various sections of an executable file.
Copyright 1991 , 19 92 Free Software Foundation , Inc .
Copyright 1991 , 92 , 93 , 94 Free Software Foundation , Inc .
This file is part of GNU Binutils .
@ -16,8 +16,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA . */
/* Extensions/incompatibilities:
o - BSD output has filenames at the end .
o - BSD output can appear in different radicies .
@ -26,62 +25,66 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
o - We also handle core files .
o - We also handle archives .
If you write shell scripts which manipulate this info then you may be
out of luck ; there ' s no - - predantic option .
out of luck ; there ' s no - - com patibility o r - - p edantic option .
*/
# include "bfd.h"
# include "sysdep.h"
# include "getopt.h"
# include "bucomm.h"
# ifndef BSD_DEFAULT
# define BSD_DEFAULT 1
# endif
/* Various program options */
/* Program options. */
enum { decimal , octal , hex } radix = decimal ;
int berkeley_format = BSD_DEFAULT ; /* 0 means use AT&T-style output */
enum
{
decimal , octal , hex
} radix = decimal ;
int berkeley_format = BSD_DEFAULT ; /* 0 means use AT&T-style output. */
int show_version = 0 ;
int show_help = 0 ;
/* Program exit status. */
int return_code = 0 ;
/* IMPORTS */
extern char * program_version ;
extern char * program_name ;
extern char * target ;
/* Forward declarations */
static void
display_file PARAMS ( ( char * filename ) ) ;
static void display_file PARAMS ( ( char * filename ) ) ;
static void
print_sizes PARAMS ( ( bfd * file ) ) ;
/** main and like trivia */
static void print_sizes PARAMS ( ( bfd * file ) ) ;
static void berkeley_sum PARAMS ( ( bfd * , sec_ptr , PTR ) ) ;
void
usage ( )
usage ( stream , status )
FILE * stream ;
int status ;
{
fprintf ( stderr , " size %s \n \
fprintf ( stream , " \
Usage : % s [ - ABdoxV ] [ - - format = berkeley | sysv ] [ - - radix = 8 | 10 | 16 ] \ n \
[ - - target = bfdname ] [ - - version ] [ - - help ] [ file . . . ] \ n " ,
program_version , program_name ) ;
[ - - target = bfdname ] [ - - version ] [ - - help ] [ file . . . ] \ n " , program_name);
# if BSD_DEFAULT
fputs ( " ( default is --format=berkeley) \n " , stder r ) ;
fputs ( " default is --format=berkeley \n " , stream ) ;
# else
fputs ( " ( default is --format=sysv) \n " , stder r ) ;
fputs ( " default is --format=sysv \n " , stream ) ;
# endif
exit ( 1 ) ;
exit ( status ) ;
}
struct option long_options [ ] = {
{ " format " , required_argument , 0 , 200 } ,
{ " radix " , required_argument , 0 , 201 } ,
{ " target " , required_argument , 0 , 202 } ,
struct option long_options [ ] =
{
{ " format " , required_argument , 0 , 200 } ,
{ " radix " , required_argument , 0 , 201 } ,
{ " target " , required_argument , 0 , 202 } ,
{ " version " , no_argument , & show_version , 1 } ,
{ " help " , no_argument , & show_help , 1 } ,
{ " help " , no_argument , & show_help , 1 } ,
{ 0 , no_argument , 0 , 0 }
} ;
@ -91,56 +94,92 @@ main (argc, argv)
char * * argv ;
{
int temp ;
int c ; /* sez which option char */
extern int optind ; /* steps thru options */
int c ;
program_name = * argv ;
bfd_init ( ) ;
while ( ( c = getopt_long ( argc , argv , " ABVdox " , long_options ,
( int * ) 0 ) ) ! = EOF )
switch ( c ) {
case 200 : /* --format */
switch ( * optarg ) {
case ' B ' : case ' b ' : berkeley_format = 1 ; break ;
case ' S ' : case ' s ' : berkeley_format = 0 ; break ;
default : fprintf ( stderr , " invalid argument to --format: %s \n " , optarg ) ;
usage ( ) ;
}
bfd_init ( ) ;
while ( ( c = getopt_long ( argc , argv , " ABVdox " , long_options ,
( int * ) 0 ) ) ! = EOF )
switch ( c )
{
case 200 : /* --format */
switch ( * optarg )
{
case ' B ' :
case ' b ' :
berkeley_format = 1 ;
break ;
case ' S ' :
case ' s ' :
berkeley_format = 0 ;
break ;
default :
fprintf ( stderr , " invalid argument to --format: %s \n " , optarg ) ;
usage ( stderr , 1 ) ;
}
break ;
case 202 : /* --target */
case 202 : /* --target */
target = optarg ;
break ;
case 201 : /* --radix */
case 201 : /* --radix */
# ifdef ANSI_LIBRARIES
temp = strtol ( optarg , NULL , 10 ) ;
temp = strtol ( optarg , NULL , 10 ) ;
# else
temp = atol ( optarg ) ;
temp = atol ( optarg ) ;
# endif
switch ( temp ) {
case 10 : radix = decimal ; break ;
case 8 : radix = octal ; break ;
case 16 : radix = hex ; break ;
default : printf ( " Unknown radix: %s \n " , optarg ) ;
usage ( ) ;
}
switch ( temp )
{
case 10 :
radix = decimal ;
break ;
case 8 :
radix = octal ;
break ;
case 16 :
radix = hex ;
break ;
default :
printf ( " Invalid radix: %s \n " , optarg ) ;
usage ( stderr , 1 ) ;
}
break ;
case ' A ' : berkeley_format = 0 ; break ;
case ' B ' : berkeley_format = 1 ; break ;
case ' V ' : show_version = 1 ; break ;
case ' d ' : radix = decimal ; break ;
case ' x ' : radix = hex ; break ;
case ' o ' : radix = octal ; break ;
case ' ? ' : usage ( ) ;
case ' A ' :
berkeley_format = 0 ;
break ;
case ' B ' :
berkeley_format = 1 ;
break ;
case ' V ' :
show_version = 1 ;
break ;
case ' d ' :
radix = decimal ;
break ;
case ' x ' :
radix = hex ;
break ;
case ' o ' :
radix = octal ;
break ;
case 0 :
break ;
case ' ? ' :
usage ( stderr , 1 ) ;
}
if ( show_version )
{
printf ( " GNU %s version %s \n " , program_name , program_version ) ;
exit ( 0 ) ;
}
if ( show_help )
usage ( stdout , 0 ) ;
if ( show_version ) printf ( " %s version %s \n " , program_name , program_version ) ;
if ( show_help ) usage ( ) ;
if ( optind = = argc )
display_file ( " a.out " ) ;
else
@ -150,82 +189,113 @@ main (argc, argv)
return return_code ;
}
/** Display a file's stats */
/* Display stats on file or archive member ABFD. */
void
display_bfd ( abfd )
bfd * abfd ;
{
CONST char * core_cmd ;
char * * matching ;
if ( bfd_check_format ( abfd , bfd_archive ) ) return ;
if ( bfd_check_format ( abfd , bfd_archive ) )
/* An archive within an archive. */
return ;
if ( bfd_check_format ( abfd , bfd_object ) ) {
print_sizes ( abfd ) ;
goto done ;
}
if ( bfd_check_format_matches ( abfd , bfd_object , & matching ) )
{
print_sizes ( abfd ) ;
printf ( " \n " ) ;
return ;
}
if ( bfd_check_format ( abfd , bfd_core ) ) {
print_sizes ( abfd ) ;
fputs ( " (core file " , stdout ) ;
if ( bfd_error = = file_ambiguously_recognized )
{
bfd_nonfatal ( bfd_get_filename ( abfd ) ) ;
list_matching_formats ( matching ) ;
free ( matching ) ;
return_code = 3 ;
return ;
}
core_cmd = bfd_core_file_failing_command ( abfd ) ;
if ( core_cmd ) printf ( " invoked as %s " , core_cmd ) ;
if ( bfd_check_format_matches ( abfd , bfd_core , & matching ) )
{
CONST char * core_cmd ;
puts ( " ) " ) ;
goto done ;
}
printf ( " Unknown file format: %s. " , bfd_get_filename ( abfd ) ) ;
return_code = 3 ;
print_sizes ( abfd ) ;
fputs ( " (core file " , stdout ) ;
done :
core_cmd = bfd_core_file_failing_command ( abfd ) ;
if ( core_cmd )
printf ( " invoked as %s " , core_cmd ) ;
puts ( " ) \n " ) ;
return ;
}
bfd_nonfatal ( bfd_get_filename ( abfd ) ) ;
if ( bfd_error = = file_ambiguously_recognized )
{
list_matching_formats ( matching ) ;
free ( matching ) ;
}
printf ( " \n " ) ;
return ;
return_code = 3 ;
}
static void
display_file ( filename )
char * filename ;
display_archive ( fil e )
bfd * file ;
{
bfd * file , * arfile = ( bfd * ) NULL ;
bfd * arfile = ( bfd * ) NULL ;
file = bfd_openr ( filename , target ) ;
if ( file = = NULL ) {
fprintf ( stderr , " %s: " , program_name ) ;
bfd_perror ( filename ) ;
return_code = 1 ;
return ;
}
if ( bfd_check_format ( file , bfd_archive ) = = true ) {
for ( ; ; ) {
for ( ; ; )
{
bfd_error = no_error ;
arfile = bfd_openr_next_archived_file ( file , arfile ) ;
if ( arfile = = NULL ) {
if ( bfd_error ! = no_more_archived_files ) {
fprintf ( stderr , " %s: " , program_name ) ;
bfd_perror ( bfd_get_filename ( file ) ) ;
return_code = 2 ;
}
return ;
}
arfile = bfd_openr_next_archived_file ( file , arfile ) ;
if ( arfile = = NULL )
{
if ( bfd_error ! = no_more_archived_files )
{
bfd_nonfatal ( bfd_get_filename ( file ) ) ;
return_code = 2 ;
}
break ;
}
display_bfd ( arfile ) ;
/* Don't close the archive elements; we need them for next_archive */
}
}
}
static void
display_file ( filename )
char * filename ;
{
bfd * file = bfd_openr ( filename , target ) ;
if ( file = = NULL )
{
bfd_nonfatal ( filename ) ;
return_code = 1 ;
return ;
}
if ( bfd_check_format ( file , bfd_archive ) = = true )
display_archive ( file ) ;
else
display_bfd ( file ) ;
bfd_close ( file ) ;
if ( bfd_close ( file ) = = false )
{
bfd_nonfatal ( filename ) ;
return_code = 1 ;
return ;
}
}
/* This is what lexical functions are for */
/* This is what lexical functions are for. */
void
lprint_number ( width , num )
int width ;
@ -233,128 +303,124 @@ lprint_number (width, num)
{
printf ( ( radix = = decimal ? " %-*lu \t " :
( ( radix = = octal ) ? " %-*lo \t " : " %-*lx \t " ) ) ,
width , ( unsigned long ) num ) ;
width , ( unsigned long ) num ) ;
}
void
rprint_number ( width , num )
rprint_number ( width , num )
int width ;
bfd_size_type num ;
{
printf ( ( radix = = decimal ? " %*lu \t " :
( ( radix = = octal ) ? " %*lo \t " : " %*lx \t " ) ) ,
width , ( unsigned long ) num ) ;
width , ( unsigned long ) num ) ;
}
static char * bss_section_name = " .bss " ;
static char * data_section_name = " .data " ;
static char * stack_section_name = " .stack " ;
static char * text_section_name = " .text " ;
static bfd_size_type bsssize ;
static bfd_size_type datasize ;
static bfd_size_type textsize ;
void print_berkeley_format ( abfd )
bfd * abfd ;
static void
berkeley_sum ( abfd , sec , ignore )
bfd * abfd ;
sec_ptr sec ;
PTR ignore ;
{
bfd_size_type size ;
size = bfd_get_section_size_before_reloc ( sec ) ;
if ( bfd_get_section_flags ( abfd , sec ) & SEC_CODE )
textsize + = size ;
else if ( bfd_get_section_flags ( abfd , sec ) & SEC_DATA )
datasize + = size ;
else if ( bfd_get_section_flags ( abfd , sec ) & SEC_ALLOC )
bsssize + = size ;
}
void
print_berkeley_format ( abfd )
bfd * abfd ;
{
static int files_seen = 0 ;
sec_ptr bsssection = NULL ;
sec_ptr datasection = NULL ;
sec_ptr textsection = NULL ;
bfd_size_type bsssize = 0 ;
bfd_size_type datasize = 0 ;
bfd_size_type textsize = 0 ;
bfd_size_type total = 0 ;
if ( ( textsection = bfd_get_section_by_name ( abfd , text_section_name ) )
! = NULL ) {
textsize = bfd_get_section_size_before_reloc ( textsection ) ;
}
if ( ( datasection = bfd_get_section_by_name ( abfd , data_section_name ) )
! = NULL ) {
datasize = bfd_get_section_size_before_reloc ( datasection ) ;
}
if ( bfd_get_format ( abfd ) = = bfd_object ) {
if ( ( bsssection = bfd_get_section_by_name ( abfd , bss_section_name ) )
! = NULL ) {
bsssize = bfd_section_size ( abfd , bsssection ) ;
}
} else {
if ( ( bsssection = bfd_get_section_by_name ( abfd , stack_section_name ) )
! = NULL ) {
bsssize = bfd_section_size ( abfd , bsssection ) ;
}
}
bfd_size_type total ;
bsssize = 0 ;
datasize = 0 ;
textsize = 0 ;
bfd_map_over_sections ( abfd , berkeley_sum , ( PTR ) NULL ) ;
if ( files_seen + + = = 0 )
#if 0 /* intel doesn't like bss/stk b/c they don't gave core files */
puts ( ( radix = = octal ) ? " text \t data \t bss/stk \t oct \t hex \t filename " :
" text \t data \t bss/stk \t dec \t hex \t filename " ) ;
#if 0
/* Intel doesn't like bss/stk because they don't have core files. */
puts ( ( radix = = octal ) ? " text \t data \t bss/stk \t oct \t hex \t filename " :
" text \t data \t bss/stk \t dec \t hex \t filename " ) ;
# else
puts ( ( radix = = octal ) ? " text \t data \t bss \t oct \t hex \t filename " :
" text \t data \t bss \t dec \t hex \t filename " ) ;
puts ( ( radix = = octal ) ? " text \t data \t bss \t oct \t hex \t filename " :
" text \t data \t bss \t dec \t hex \t filename " ) ;
# endif
total = textsize + datasize + bsssize ;
lprint_number ( 7 , textsize ) ;
lprint_number ( 7 , datasize ) ;
lprint_number ( 7 , bsssize ) ;
printf ( ( ( radix = = octal ) ? " %-7lo \t %-7lx \t " : " %-7lu \t %-7lx \t " ) ,
( unsigned long ) total , ( unsigned long ) total ) ;
( unsigned long ) total , ( unsigned long ) total ) ;
fputs ( bfd_get_filename ( abfd ) , stdout ) ;
if ( abfd - > my_archive ) printf ( " (ex %s) " , abfd - > my_archive - > filename ) ;
fputs ( bfd_get_filename ( abfd ) , stdout ) ;
if ( abfd - > my_archive )
printf ( " (ex %s) " , abfd - > my_archive - > filename ) ;
}
/* I REALLY miss lexical functions! */
bfd_size_type svi_total = 0 ;
void
sysv_internal_printer ( file , sec , ignore )
sysv_internal_printer ( file , sec , ignore )
bfd * file ;
sec_ptr sec ;
PTR ignore ;
{
bfd_size_type size = bfd_section_size ( file , sec ) ;
if ( sec ! = & bfd_abs_section
& & ! bfd_is_com_section ( sec )
& & sec ! = & bfd_und_section )
{
svi_total + = size ;
printf ( " %-12s " , bfd_section_name ( file , sec ) ) ;
rprint_number ( 8 , size ) ;
printf ( " " ) ;
rprint_number ( 8 , bfd_section_vma ( file , sec ) ) ;
printf ( " \n " ) ;
}
if ( sec ! = & bfd_abs_section
& & ! bfd_is_com_section ( sec )
& & sec ! = & bfd_und_section )
{
svi_total + = size ;
printf ( " %-12s " , bfd_section_name ( file , sec ) ) ;
rprint_number ( 8 , size ) ;
printf ( " " ) ;
rprint_number ( 8 , bfd_section_vma ( file , sec ) ) ;
printf ( " \n " ) ;
}
}
void
print_sysv_format ( file )
print_sysv_format ( file )
bfd * file ;
{
svi_total = 0 ;
printf ( " %s " , bfd_get_filename ( file ) ) ;
if ( file - > my_archive ) printf ( " (ex %s) " , file - > my_archive - > filename ) ;
if ( file - > my_archive )
printf ( " (ex %s) " , file - > my_archive - > filename ) ;
puts ( " : \n section \t \t size \t addr " ) ;
bfd_map_over_sections ( file , sysv_internal_printer , ( PTR ) NULL ) ;
puts ( " : \n section \t \t size \t addr " ) ;
bfd_map_over_sections ( file , sysv_internal_printer , ( PTR ) NULL ) ;
printf ( " Total " ) ;
rprint_number ( 8 , svi_total ) ;
printf ( " \n " ) ; printf ( " \n " ) ;
printf ( " Total " ) ;
rprint_number ( 8 , svi_total ) ;
printf ( " \n \n " ) ;
}
static void
print_sizes ( file )
print_sizes ( file )
bfd * file ;
{
if ( berkeley_format )
print_berkeley_format ( file ) ;
else print_sysv_format ( file ) ;
print_berkeley_format ( file ) ;
else
print_sysv_format ( file ) ;
}