From cef35d488209227385e0aa9ab92ebf5a861c3780 Mon Sep 17 00:00:00 2001 From: David MacKenzie Date: Thu, 3 Feb 1994 00:25:30 +0000 Subject: [PATCH] * nlmconv.c (main), objcopy.c (copy_file): Print matching formats if ambiguous match. * nm.c (display_file), size.c (display_bfd): Eliminate gotos. Print matching formats if there is an ambiguous match. Use bfd_nonfatal instead of hardcoded error message if nothing matches. * arsup.c, ar.c, objdump.c: Use bfd_get_filename instead of abfd->filename. * nm.c (display_archive): New function, from code in display_file. (display_rel_file): Renamed from do_one_rel_file. * size.c: Indent. (display_archive): New function from code in display_file. (display_file): Check bfd_close error return. * strings.c (strings_object_file): Check bfd_check_format error return. * strings.c, objdump.c, size.c: Use bfd_nonfatal instead of bfd_perror. * bucomm.c: Delete references to exit_handler. It wasn't set anywhere, and now that we're using the libiberty xmalloc, it wouldn't always get called before exiting. (list_matching_formats): Function moved from objdump.c. * bucomm.h: Declare it. * objdump.c (disassemble_data): Move some variable decls closer to their use. Add some comments. Replace a nested block with a return. --- binutils/ChangeLog | 33 ++ binutils/ar.c | 24 +- binutils/nlmconv.c | 15 +- binutils/nm.c | 893 ++++++++++++++++++++++++++++++++++----------- binutils/objcopy.c | 31 +- binutils/objdump.c | 210 +++++------ binutils/size.c | 428 +++++++++++++--------- binutils/strings.c | 68 ++-- 8 files changed, 1141 insertions(+), 561 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index df72b101d3..ff29b2b450 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,36 @@ +Wed Feb 2 13:42:23 1994 David J. Mackenzie (djm@thepub.cygnus.com) + + * nlmconv.c (main), objcopy.c (copy_file): Print matching formats + if ambiguous match. + * nm.c (display_file), size.c (display_bfd): Eliminate gotos. + Print matching formats if there is an ambiguous match. Use + bfd_nonfatal instead of hardcoded error message if nothing matches. + + * arsup.c, ar.c, objdump.c: Use bfd_get_filename instead of + abfd->filename. + + * nm.c (display_archive): New function, from code in display_file. + (display_rel_file): Renamed from do_one_rel_file. + + * size.c: Indent. + (display_archive): New function from code in display_file. + (display_file): Check bfd_close error return. + + * strings.c (strings_object_file): Check bfd_check_format + error return. + + * strings.c, objdump.c, size.c: Use bfd_nonfatal instead of bfd_perror. + + * bucomm.c: Delete references to exit_handler. It wasn't set + anywhere, and now that we're using the libiberty xmalloc, it + wouldn't always get called before exiting. + (list_matching_formats): Function moved from objdump.c. + * bucomm.h: Declare it. + + * objdump.c (disassemble_data): Move some variable decls closer to + their use. Add some comments. Replace a nested block with a + return. + Mon Jan 31 18:50:41 1994 Stan Shebs (shebs@andros.cygnus.com) * objdump.c (display_target_list, display_info_table): Check that diff --git a/binutils/ar.c b/binutils/ar.c index ec6b50884a..32d1de1605 100644 --- a/binutils/ar.c +++ b/binutils/ar.c @@ -502,10 +502,10 @@ print_contents(abfd) struct stat buf; long size; if (bfd_stat_arch_elt(abfd, &buf) != 0) - fatal("internal stat error on %s", abfd->filename); + fatal("internal stat error on %s", bfd_get_filename (abfd)); if (verbose) - printf("\n\n\n", abfd->filename); + printf("\n\n\n", bfd_get_filename (abfd)); bfd_seek(abfd, 0, SEEK_SET); @@ -552,20 +552,20 @@ extract_file(abfd) long size; struct stat buf; if (bfd_stat_arch_elt(abfd, &buf) != 0) - fatal("internal stat error on %s", abfd->filename); + fatal("internal stat error on %s", bfd_get_filename (abfd)); size = buf.st_size; if (verbose) - printf("x - %s\n", abfd->filename); + printf("x - %s\n", bfd_get_filename (abfd)); bfd_seek(abfd, 0, SEEK_SET); ostream = 0; if (size == 0) { /* Seems like an abstraction violation, eh? Well it's OK! */ - ostream = fopen(abfd->filename, FOPEN_WB); + ostream = fopen(bfd_get_filename (abfd), FOPEN_WB); if (!ostream) { - perror(abfd->filename); + perror(bfd_get_filename (abfd)); exit(1); } } else @@ -581,9 +581,9 @@ extract_file(abfd) /* See comment above; this saves disk arm motion */ if (!ostream) { /* Seems like an abstraction violation, eh? Well it's OK! */ - ostream = fopen(abfd->filename, FOPEN_WB); + ostream = fopen(bfd_get_filename (abfd), FOPEN_WB); if (!ostream) { - perror(abfd->filename); + perror(bfd_get_filename (abfd)); exit(1); } } @@ -592,27 +592,27 @@ extract_file(abfd) } fclose(ostream); - chmod(abfd->filename, buf.st_mode); + chmod(bfd_get_filename (abfd), buf.st_mode); if (preserve_dates) { #ifdef POSIX_UTIME struct utimbuf tb; tb.actime = buf.st_mtime; tb.modtime = buf.st_mtime; - utime(abfd->filename, &tb); /* FIXME check result */ + utime(bfd_get_filename (abfd), &tb); /* FIXME check result */ #else /* ! POSIX_UTIME */ #ifdef USE_UTIME long tb[2]; tb[0] = buf.st_mtime; tb[1] = buf.st_mtime; - utime(abfd->filename, tb); /* FIXME check result */ + utime(bfd_get_filename (abfd), tb); /* FIXME check result */ #else /* ! USE_UTIME */ struct timeval tv[2]; tv[0].tv_sec = buf.st_mtime; tv[0].tv_usec = 0; tv[1].tv_sec = buf.st_mtime; tv[1].tv_usec = 0; - utimes(abfd->filename, tv); /* FIXME check result */ + utimes(bfd_get_filename (abfd), tv); /* FIXME check result */ #endif /* ! USE_UTIME */ #endif /* ! POSIX_UTIME */ } diff --git a/binutils/nlmconv.c b/binutils/nlmconv.c index 812fe8b590..65f971c36e 100644 --- a/binutils/nlmconv.c +++ b/binutils/nlmconv.c @@ -171,6 +171,7 @@ main (argc, argv) Nlm_Internal_Fixed_Header sharedhdr; int len; char *modname; + char **matching; program_name = argv[0]; @@ -296,8 +297,16 @@ main (argc, argv) if (inbfd == NULL) bfd_fatal (input_file); - if (! bfd_check_format (inbfd, bfd_object)) - bfd_fatal (input_file); + if (! bfd_check_format_matches (inbfd, bfd_object, &matching)) + { + bfd_nonfatal (input_file); + if (bfd_error == file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + exit (1); + } if (output_format == NULL) output_format = select_output_format (bfd_get_arch (inbfd), @@ -493,7 +502,7 @@ main (argc, argv) { newsymalloc += 10; newsyms = ((asymbol **) - xrealloc (newsyms, + xrealloc ((PTR) newsyms, (newsymalloc * sizeof (asymbol *)))); } diff --git a/binutils/nm.c b/binutils/nm.c index 4fe3e58eb5..c3045ee40f 100644 --- a/binutils/nm.c +++ b/binutils/nm.c @@ -1,21 +1,21 @@ /* nm.c -- Describe symbol table of a rel file. - Copyright 1991, 1992 Free Software Foundation, Inc. + Copyright 1991, 92, 93, 94 Free Software Foundation, Inc. -This file is part of GNU Binutils. + This file is part of GNU Binutils. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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 02139, USA. */ + 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 02139, USA. */ #include "bfd.h" #include "sysdep.h" @@ -23,36 +23,150 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "getopt.h" #include "aout/stab_gnu.h" #include "aout/ranlib.h" +#include "demangle.h" static boolean display_file PARAMS ((char *filename)); static void -do_one_rel_file PARAMS ((bfd* file, bfd *archive)); +display_rel_file PARAMS ((bfd * file, bfd * archive)); static unsigned int -filter_symbols PARAMS ((bfd *file, asymbol **syms, unsigned long symcount)); +filter_symbols PARAMS ((bfd * file, asymbol ** syms, unsigned long symcount)); static void -print_symbols PARAMS ((bfd *file, asymbol **syms, unsigned long symcount, - bfd *archive)); +print_symbols PARAMS ((bfd * file, asymbol ** syms, unsigned long symcount, + bfd * archive)); static void print_symdef_entry PARAMS ((bfd * abfd)); + +/* The output formatting functions. */ + +static void +print_object_filename_bsd PARAMS ((char *filename)); + +static void +print_object_filename_sysv PARAMS ((char *filename)); + +static void +print_object_filename_posix PARAMS ((char *filename)); + + +static void +print_archive_filename_bsd PARAMS ((char *filename)); + +static void +print_archive_filename_sysv PARAMS ((char *filename)); + +static void +print_archive_filename_posix PARAMS ((char *filename)); + + +static void +print_archive_member_bsd PARAMS ((char *archive, CONST char *filename)); + +static void +print_archive_member_sysv PARAMS ((char *archive, CONST char *filename)); + +static void +print_archive_member_posix PARAMS ((char *archive, CONST char *filename)); + + +static void +print_symbol_filename_bsd PARAMS ((bfd * archive_bfd, bfd * abfd)); + +static void +print_symbol_filename_sysv PARAMS ((bfd * archive_bfd, bfd * abfd)); + +static void +print_symbol_filename_posix PARAMS ((bfd * archive_bfd, bfd * abfd)); + + +static void +print_symbol_info_bsd PARAMS ((symbol_info * info, bfd * abfd)); + +static void +print_symbol_info_sysv PARAMS ((symbol_info * info, bfd * abfd)); + +static void +print_symbol_info_posix PARAMS ((symbol_info * info, bfd * abfd)); + + +/* Support for different output formats. */ +struct output_fns + { + /* Print the name of an object file given on the command line. */ + void (*print_object_filename) PARAMS ((char *filename)); + + /* Print the name of an archive file given on the command line. */ + void (*print_archive_filename) PARAMS ((char *filename)); + + /* Print the name of an archive member file. */ + void (*print_archive_member) PARAMS ((char *archive, CONST char *filename)); + + /* Print the name of the file (and archive, if there is one) + containing a symbol. */ + void (*print_symbol_filename) PARAMS ((bfd * archive_bfd, bfd * abfd)); + + /* Print a line of information about a symbol. */ + void (*print_symbol_info) PARAMS ((symbol_info * info, bfd * abfd)); + }; +static struct output_fns formats[] = +{ + {print_object_filename_bsd, + print_archive_filename_bsd, + print_archive_member_bsd, + print_symbol_filename_bsd, + print_symbol_info_bsd}, + {print_object_filename_sysv, + print_archive_filename_sysv, + print_archive_member_sysv, + print_symbol_filename_sysv, + print_symbol_info_sysv}, + {print_object_filename_posix, + print_archive_filename_posix, + print_archive_member_posix, + print_symbol_filename_posix, + print_symbol_info_posix} +}; + +/* Indices in `formats'. */ +#define FORMAT_BSD 0 +#define FORMAT_SYSV 1 +#define FORMAT_POSIX 2 +#define FORMAT_DEFAULT FORMAT_BSD + +/* The output format to use. */ +static struct output_fns *format = &formats[FORMAT_DEFAULT]; + + /* Command options. */ -int external_only = 0; /* print external symbols only */ -int file_on_each_line = 0; /* print file name on each line */ -int no_sort = 0; /* don't sort; print syms in order found */ -int print_debug_syms = 0; /* print debugger-only symbols too */ -int print_armap = 0; /* describe __.SYMDEF data in archive files. */ -int reverse_sort = 0; /* sort in downward(alpha or numeric) order */ -int sort_numerically = 0; /* sort in numeric rather than alpha order */ -int undefined_only = 0; /* print undefined symbols only */ -int show_version = 0; /* show the version number */ +static int do_demangle = 0; /* Pretty print C++ symbol names. */ +static int external_only = 0; /* print external symbols only */ +static int no_sort = 0; /* don't sort; print syms in order found */ +static int print_debug_syms = 0; /* print debugger-only symbols too */ +static int print_armap = 0; /* describe __.SYMDEF data in archive files. */ +static int reverse_sort = 0; /* sort in downward(alpha or numeric) order */ +static int sort_numerically = 0; /* sort in numeric rather than alpha order */ +static int undefined_only = 0; /* print undefined symbols only */ +static int show_version = 0; /* show the version number */ -boolean print_each_filename = false; /* Ick. Used in archives. */ +/* When to print the names of files. Not mutually exclusive in SYSV format. */ +static int filename_per_file = 0; /* Once per file, on its own line. */ +static int filename_per_symbol = 0; /* Once per symbol, at start of line. */ + +/* Print formats for printing a symbol value. */ +#ifdef HOST_64_BIT +static char value_format[] = "%08x%08x"; +#else +static char value_format[] = "%08lx"; +#endif +/* Print formats for printing stab info. */ +static char other_format[] = "%02x"; +static char desc_format[] = "%04x"; /* IMPORT */ extern char *program_name; @@ -60,98 +174,227 @@ extern char *program_version; extern char *target; extern int print_version; -struct option long_options[] = { - {"debug-syms", no_argument, &print_debug_syms, 1}, - {"extern-only", no_argument, &external_only, 1}, - {"no-sort", no_argument, &no_sort, 1}, - {"numeric-sort", no_argument, &sort_numerically, 1}, - {"print-armap", no_argument, &print_armap, 1}, - {"print-file-name", no_argument, &file_on_each_line, 1}, - {"reverse-sort", no_argument, &reverse_sort, 1}, - {"target", optional_argument, 0, 200}, - {"undefined-only", no_argument, &undefined_only, 1}, - {"version", no_argument, &show_version, 1}, - {0, no_argument, 0, 0} +static struct option long_options[] = +{ + {"debug-syms", no_argument, &print_debug_syms, 1}, + {"demangle", no_argument, &do_demangle, 1}, + {"extern-only", no_argument, &external_only, 1}, + {"format", required_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, + {"no-sort", no_argument, &no_sort, 1}, + {"numeric-sort", no_argument, &sort_numerically, 1}, + {"portability", no_argument, 0, 'P'}, + {"print-armap", no_argument, &print_armap, 1}, + {"print-file-name", no_argument, 0, 'o'}, + {"radix", required_argument, 0, 't'}, + {"reverse-sort", no_argument, &reverse_sort, 1}, + {"target", required_argument, 0, 200}, + {"undefined-only", no_argument, &undefined_only, 1}, + {"version", no_argument, &show_version, 1}, + {0, no_argument, 0, 0} }; - -int show_names = 0; /* Some error-reporting functions */ void -usage () +usage (stream, status) + FILE *stream; + int status; { - fprintf(stderr, "nm %s\n\ -Usage: %s [-agnoprsuV] [--debug-syms] [--extern-only] [--print-armap]\n\ - [--print-file-name] [--numeric-sort] [--no-sort] [--reverse-sort]\n\ - [--undefined-only] [--target=bfdname] [file...]\n", - program_version, program_name); - exit(1); + fprintf (stream, "\ +Usage: %s [-aABCgnopPrsuvV] [-t radix] [--radix=radix] [--target=bfdname]\n\ + [--debug-syms] [--extern-only] [--print-armap] [--print-file-name]\n\ + [--numeric-sort] [--no-sort] [--reverse-sort] [--undefined-only]\n\ + [--portability] [-f {bsd,sysv,posix}] [--format={bsd,sysv,posix}]\n\ + [--demangle] [--version] [--help] [file...]\n", + program_name); + exit (status); } +/* Set the radix for the symbol value and size according to RADIX. */ + +void +set_print_radix (radix) + char *radix; +{ + switch (*radix) + { + case 'd': + case 'o': + case 'x': +#ifdef HOST_64_BIT + value_format[3] = value_format[7] = *radix; +#else + value_format[4] = *radix; +#endif + other_format[3] = desc_format[3] = *radix; + break; + default: + fprintf (stderr, "%s: %s: invalid radix\n", program_name, radix); + exit (1); + } +} + +void +set_output_format (f) + char *f; +{ + int i; + + switch (*f) + { + case 'b': + case 'B': + i = FORMAT_BSD; + break; + case 'p': + case 'P': + i = FORMAT_POSIX; + break; + case 's': + case 'S': + i = FORMAT_SYSV; + break; + default: + fprintf (stderr, "%s: %s: invalid output format\n", program_name, f); + exit (1); + } + format = &formats[i]; +} + int main (argc, argv) int argc; char **argv; { - int c; /* sez which option char */ + int c; int retval; + program_name = *argv; - bfd_init(); + bfd_init (); - while ((c = getopt_long(argc, argv, "agnoprsuvABV", long_options, (int *) 0)) != EOF) { - switch (c) { - case 'a': print_debug_syms = 1; break; - case 'g': external_only = 1; break; - case 'n': sort_numerically = 1; break; - case 'o': file_on_each_line = 1; break; - case 'p': no_sort = 1; break; - case 'r': reverse_sort = 1; break; - case 's': print_armap = 1; break; - case 'u': undefined_only = 1; break; - case 'v': - case 'V': show_version = 1; break; + while ((c = getopt_long (argc, argv, "aABCf:gnopPrst:uvV", long_options, (int *) 0)) != EOF) + { + switch (c) + { + case 'a': + print_debug_syms = 1; + break; + case 'A': + case 'o': + filename_per_symbol = 1; + break; + case 'B': /* For MIPS compatibility. */ + set_output_format ("bsd"); + break; + case 'C': + do_demangle = 1; + break; + case 'f': + set_output_format (optarg); + break; + case 'g': + external_only = 1; + break; + case 'h': + usage (stdout, 0); + case 'n': + case 'v': + sort_numerically = 1; + break; + case 'p': + no_sort = 1; + break; + case 'P': + set_output_format ("posix"); + break; + case 'r': + reverse_sort = 1; + break; + case 's': + print_armap = 1; + break; + case 't': + set_print_radix (optarg); + break; + case 'u': + undefined_only = 1; + break; + case 'V': + show_version = 1; + break; - /* For MIPS compatibility, -A selects System V style output, -B - selects BSD style output. These are not implemented. When - they are, they should be added to usage (). */ - case 'A': break; - case 'B': break; + case 200: /* --target */ + target = optarg; + break; - case 200: /* --target */ - target = optarg; - break; + case 0: /* A long option that just sets a flag. */ + break; - default: - usage (); + default: + usage (stderr, 1); + } } - } if (show_version) - printf ("%s version %s\n", program_name, program_version); + { + printf ("GNU %s version %s\n", program_name, program_version); + exit (0); + } - /* Strangely, for the shell you should return only a nonzero value - on sucess -- the inverse of the C sense. */ - - /* OK, all options now parsed. If no filename specified, do a.out. */ - if (optind == argc) return !display_file ("a.out"); + /* OK, all options now parsed. If no filename specified, do a.out. */ + if (optind == argc) + return !display_file ("a.out"); retval = 0; - show_names = (argc -optind)>1; - /* We were given several filenames to do: */ - while (optind < argc) { - if (!display_file (argv[optind++])) { - retval++; - } - } + if (argc - optind > 1) + filename_per_file = 1; + + /* We were given several filenames to do. */ + while (optind < argc) + { + if (!display_file (argv[optind++])) + retval++; + } + + exit (retval); return retval; } -/* Display a file's stats */ +static void +display_archive (file) + bfd *file; +{ + bfd *arfile = NULL; -/* goto here is marginally cleaner than the nested if syntax */ + (*format->print_archive_filename) (bfd_get_filename (file)); + + if (print_armap) + print_symdef_entry (file); + + for (;;) + { + arfile = bfd_openr_next_archived_file (file, arfile); + + if (arfile == NULL) + { + if (bfd_error != no_more_archived_files) + bfd_fatal (bfd_get_filename (file)); + break; + } + + if (bfd_check_format (arfile, bfd_object)) + { + (*format->print_archive_member) (bfd_get_filename (file), + bfd_get_filename (arfile)); + display_rel_file (arfile, file); + } + else + printf ("%s: not an object file\n", arfile->filename); + } +} static boolean display_file (filename) @@ -159,57 +402,36 @@ display_file (filename) { boolean retval = true; bfd *file; - bfd *arfile = NULL; + char **matching; - file = bfd_openr(filename, target); - if (file == NULL) { - fprintf (stderr, "%s: ", program_name); - bfd_perror (filename); - return false; - } + file = bfd_openr (filename, target); + if (file == NULL) + { + bfd_nonfatal (filename); + return false; + } - if (bfd_check_format(file, bfd_object)) - { - if (show_names) { - printf ("\n%s:\n",filename); + if (bfd_check_format (file, bfd_archive)) + { + display_archive (file); + } + else if (bfd_check_format_matches (file, bfd_object, &matching)) + { + (*format->print_object_filename) (filename); + display_rel_file (file, NULL); + } + else + { + bfd_nonfatal (filename); + if (bfd_error == file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); } - do_one_rel_file (file, NULL); - } - else if (bfd_check_format (file, bfd_archive)) { - if (!bfd_check_format (file, bfd_archive)) { - fprintf (stderr, "%s: %s: unknown format\n", program_name, filename); retval = false; - goto closer; } - if (!file_on_each_line) - printf("\n%s:\n", filename); - if (print_armap) print_symdef_entry (file); - for (;;) { - arfile = bfd_openr_next_archived_file (file, arfile); - - if (arfile == NULL) { - if (bfd_error != no_more_archived_files) - bfd_fatal (filename); - goto closer; - } - - if (!bfd_check_format(arfile, bfd_object)) - printf("%s: not an object file\n", arfile->filename); - else { - if (!file_on_each_line) - printf ("\n%s:\n", arfile->filename); - do_one_rel_file (arfile, file) ; - } - } - } - else { - fprintf (stderr, "\n%s: %s: unknown format\n", program_name, filename); - retval = false; - } - - closer: - if (bfd_close(file) == false) + if (bfd_close (file) == false) bfd_fatal (filename); return retval; @@ -222,7 +444,7 @@ numeric_forward (x, y) CONST void *x; CONST void *y; { - return (valueof(*(asymbol **)x) - valueof(*(asymbol **) y)); + return (valueof (*(asymbol **) x) - valueof (*(asymbol **) y)); } int @@ -230,7 +452,7 @@ numeric_reverse (x, y) CONST void *x; CONST void *y; { - return (valueof(*(asymbol **)y) - valueof(*(asymbol **) x)); + return (valueof (*(asymbol **) y) - valueof (*(asymbol **) x)); } int @@ -253,50 +475,56 @@ non_numeric_reverse (x, y) return -(non_numeric_forward (x, y)); } -int (*(sorters[2][2])) PARAMS ((CONST void *, CONST void *)) = { - {non_numeric_forward, non_numeric_reverse}, - {numeric_forward, numeric_reverse}, +static int (*(sorters[2][2])) PARAMS ((CONST void *, CONST void *)) = +{ + { non_numeric_forward, non_numeric_reverse }, + { numeric_forward, numeric_reverse } }; +/* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. */ + static void -do_one_rel_file (abfd, archive_bfd) +display_rel_file (abfd, archive_bfd) bfd *abfd; - bfd *archive_bfd; /* If non-NULL: archive containing abfd. */ + bfd *archive_bfd; { unsigned int storage; asymbol **syms; unsigned int symcount = 0; - if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) { - (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd)); - return; - } + if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) + { + printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd)); + return; + } storage = get_symtab_upper_bound (abfd); - if (storage == 0) { - nosymz: - fprintf (stderr, "%s: Symflags set but there are none?\n", - bfd_get_filename (abfd)); - return; - } + if (storage == 0) + { + nosymz: + fprintf (stderr, "%s: Symflags set but there are none?\n", + bfd_get_filename (abfd)); + return; + } syms = (asymbol **) xmalloc (storage); symcount = bfd_canonicalize_symtab (abfd, syms); - if (symcount == 0) goto nosymz; + if (symcount == 0) + { + free (syms); + goto nosymz; + } /* Discard the symbols we don't want to print. It's OK to do this in place; we'll free the storage anyway - (after printing) */ + (after printing). */ symcount = filter_symbols (abfd, syms, symcount); if (!no_sort) - qsort((char *) syms, symcount, sizeof (asymbol *), - sorters[sort_numerically][reverse_sort]); - - if (print_each_filename && !file_on_each_line) - printf("\n%s:\n", bfd_get_filename(abfd)); + qsort ((char *) syms, symcount, sizeof (asymbol *), + sorters[sort_numerically][reverse_sort]); print_symbols (abfd, syms, symcount, archive_bfd); free (syms); @@ -305,44 +533,75 @@ do_one_rel_file (abfd, archive_bfd) /* Choose which symbol entries to print; compact them downward to get rid of the rest. Return the number of symbols to be printed. */ + static unsigned int filter_symbols (abfd, syms, symcount) - bfd *abfd; + bfd *abfd; /* Unused. */ asymbol **syms; unsigned long symcount; { asymbol **from, **to; + unsigned int src_count; unsigned int dst_count = 0; asymbol *sym; - unsigned int src_count; - for (from = to = syms, src_count = 0; src_count flags; - flagword flags = (from[src_count])->flags; - sym = from[src_count]; - if (undefined_only) { - keep = sym->section == &bfd_und_section; - } else if (external_only) { - keep = ((flags & BSF_GLOBAL) - || (sym->section == &bfd_und_section) - || (bfd_is_com_section (sym->section))); - } else { - keep = 1; - } + sym = from[src_count]; + if (undefined_only) + keep = sym->section == &bfd_und_section; + else if (external_only) + keep = ((flags & BSF_GLOBAL) + || (sym->section == &bfd_und_section) + || (bfd_is_com_section (sym->section))); + else + keep = 1; - if (!print_debug_syms && ((flags & BSF_DEBUGGING) != 0)) { - keep = 0; - } + if (!print_debug_syms && ((flags & BSF_DEBUGGING) != 0)) + keep = 0; - if (keep) { - to[dst_count++] = from[src_count]; + if (keep) + to[dst_count++] = from[src_count]; } - } return dst_count; } +/* Print symbol name NAME, read from ABFD, with printf format FORMAT, + demangling it if requested. */ + +static void +print_symname (format, name, abfd) + char *format, *name; + bfd *abfd; +{ + if (do_demangle) + { + char *res; + + /* In this mode, give a user-level view of the symbol name + even if it's not mangled; strip off any leading + underscore. */ + if (bfd_get_symbol_leading_char (abfd) == name[0]) + name++; + + res = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS); + if (res) + { + printf (format, res); + free (res); + return; + } + } + + printf (format, name); +} + +/* If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. */ + static void print_symbols (abfd, syms, symcount, archive_bfd) bfd *abfd; @@ -351,31 +610,250 @@ print_symbols (abfd, syms, symcount, archive_bfd) bfd *archive_bfd; { asymbol **sym = syms, **end = syms + symcount; + symbol_info syminfo; - for (; sym < end; ++sym) { - if (file_on_each_line) { - if (archive_bfd) - printf("%s:", bfd_get_filename(archive_bfd)); - printf("%s:", bfd_get_filename(abfd)); - } + for (; sym < end; ++sym) + { + (*format->print_symbol_filename) (archive_bfd, abfd); - if (undefined_only) { - if ((*sym)->section == &bfd_und_section) - puts ((*sym)->name); + if (undefined_only) + { + if ((*sym)->section == &bfd_und_section) + { + print_symname ("%s\n", (*sym)->name, abfd); + } + } + else + { + asymbol *p = *sym; + if (p) + { + bfd_get_symbol_info (abfd, p, &syminfo); + (*format->print_symbol_info) (&syminfo, abfd); + putchar ('\n'); + } + } } - else { - asymbol *p = *sym; - if (p) { - bfd_print_symbol(abfd, stdout, p, bfd_print_symbol_nm); - putchar('\n'); - } - } - } +} + +/* The following 3 groups of functions are called unconditionally, + once at the start of processing each file of the appropriate type. + They should check `filename_per_file' and `filename_per_symbol', + as appropriate for their output format, to determine whether to + print anything. */ + +/* Print the name of an object file given on the command line. */ + +static void +print_object_filename_bsd (filename) + char *filename; +{ + if (filename_per_file && !filename_per_symbol) + printf ("\n%s:\n", filename); } +static void +print_object_filename_sysv (filename) + char *filename; +{ + if (undefined_only) + printf ("\n\nUndefined symbols from %s:\n\n", filename); + else + printf ("\n\nSymbols from %s:\n\n", filename); + printf ("\ +Name Value Class Type Size Line Section\n\n"); +} + +static void +print_object_filename_posix (filename) + char *filename; +{ + if (filename_per_file && !filename_per_symbol) + printf ("%s:\n", filename); +} + +/* Print the name of an archive file given on the command line. */ + +static void +print_archive_filename_bsd (filename) + char *filename; +{ + if (filename_per_file) + printf ("\n%s:\n", filename); +} + +static void +print_archive_filename_sysv (filename) + char *filename; +{ +} + +static void +print_archive_filename_posix (filename) + char *filename; +{ +} + +/* Print the name of an archive member file. */ + +static void +print_archive_member_bsd (archive, filename) + char *archive; + CONST char *filename; +{ + if (!filename_per_symbol) + printf ("\n%s:\n", filename); +} + +static void +print_archive_member_sysv (archive, filename) + char *archive; + CONST char *filename; +{ + if (undefined_only) + printf ("\n\nUndefined symbols from %s[%s]:\n\n", archive, filename); + else + printf ("\n\nSymbols from %s[%s]:\n\n", archive, filename); + printf ("\ +Name Value Class Type Size Line Section\n\n"); +} + +static void +print_archive_member_posix (archive, filename) + char *archive; + CONST char *filename; +{ + if (!filename_per_symbol) + printf ("%s[%s]:\n", archive, filename); +} + +/* Print the name of the file (and archive, if there is one) + containing a symbol. */ + +static void +print_symbol_filename_bsd (archive_bfd, abfd) + bfd *archive_bfd, *abfd; +{ + if (filename_per_symbol) + { + if (archive_bfd) + printf ("%s:", bfd_get_filename (archive_bfd)); + printf ("%s:", bfd_get_filename (abfd)); + } +} + +static void +print_symbol_filename_sysv (archive_bfd, abfd) + bfd *archive_bfd, *abfd; +{ + if (filename_per_symbol) + { + if (archive_bfd) + printf ("%s:", bfd_get_filename (archive_bfd)); + printf ("%s:", bfd_get_filename (abfd)); + } +} + +static void +print_symbol_filename_posix (archive_bfd, abfd) + bfd *archive_bfd, *abfd; +{ + if (filename_per_symbol) + { + if (archive_bfd) + printf ("%s[%s]: ", bfd_get_filename (archive_bfd), + bfd_get_filename (abfd)); + else + printf ("%s: ", bfd_get_filename (abfd)); + } +} + +/* Print a line of information about a symbol. */ + +static void +print_symbol_info_bsd (info, abfd) + symbol_info *info; + bfd *abfd; +{ + if (info->type == 'U') + printf (" "); + else + { +#ifdef HOST_64_BIT + printf (value_format, uint64_typeHIGH (info->value), + uint64_typeLOW (info->value)); +#else + printf (value_format, info->value); +#endif + } + printf (" %c", info->type); + if (info->type == '-') + { + /* A stab. */ + printf (" "); + printf (other_format, info->stab_other); + printf (" "); + printf (desc_format, info->stab_desc); + printf (" %5s", info->stab_name); + } + print_symname (" %s", info->name, abfd); +} + +static void +print_symbol_info_sysv (info, abfd) + symbol_info *info; + bfd *abfd; +{ + print_symname ("%-20s|", info->name, abfd); /* Name */ + if (info->type == 'U') + printf (" "); /* Value */ + else + { +#ifdef HOST_64_BIT + printf (value_format, uint64_typeHIGH (info->value), + uint64_typeLOW (info->value)); +#else + printf (value_format, info->value); +#endif + } + printf ("| %c |", info->type); /* Class */ + if (info->type == '-') + { + /* A stab. */ + printf ("%18s| ", info->stab_name); /* (C) Type */ + printf (desc_format, info->stab_desc); /* Size */ + printf ("| |"); /* Line, Section */ + } + else + printf (" | | |"); /* Type, Size, Line, Section */ +} + +static void +print_symbol_info_posix (info, abfd) + symbol_info *info; + bfd *abfd; +{ + print_symname ("%s ", info->name, abfd); + printf ("%c ", info->type); + if (info->type == 'U') + printf (" "); + else + { +#ifdef HOST_64_BIT + printf (value_format, uint64_typeHIGH (info->value), + uint64_typeLOW (info->value)); +#else + printf (value_format, info->value); +#endif + } + /* POSIX.2 wants the symbol size printed here, when applicable; + BFD currently doesn't provide it, so we take the easy way out by + considering it to never be applicable. */ +} + static void print_symdef_entry (abfd) - bfd * abfd; + bfd *abfd; { symindex idx = BFD_NO_MORE_SYMBOLS; carsym *thesym; @@ -383,15 +861,18 @@ print_symdef_entry (abfd) for (idx = bfd_get_next_mapent (abfd, idx, &thesym); idx != BFD_NO_MORE_SYMBOLS; - idx = bfd_get_next_mapent (abfd, idx, &thesym)) { - bfd *elt; - if (!everprinted) { - printf ("\nArchive index:\n"); - everprinted = true; + idx = bfd_get_next_mapent (abfd, idx, &thesym)) + { + bfd *elt; + if (!everprinted) + { + printf ("\nArchive index:\n"); + everprinted = true; + } + elt = bfd_get_elt_at_index (abfd, idx); + if (thesym->name != (char *) NULL) + { + printf ("%s in %s\n", thesym->name, bfd_get_filename (elt)); + } } - elt = bfd_get_elt_at_index (abfd, idx); - if (thesym->name != (char *)NULL) { - printf ("%s in %s\n", thesym->name, bfd_get_filename (elt)); - } - } } diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 01eb6c0238..954abb8e05 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -390,6 +390,7 @@ copy_file (input_filename, output_filename, input_target, output_target) char *output_target; { bfd *ibfd; + char **matching; /* To allow us to do "strip *" without dying on the first non-object file, failures are nonfatal. */ @@ -400,7 +401,16 @@ copy_file (input_filename, output_filename, input_target, output_target) nonfatal (input_filename); } - if (bfd_check_format (ibfd, bfd_object)) + if (bfd_check_format (ibfd, bfd_archive)) + { + bfd *obfd = bfd_openw (output_filename, output_target); + if (obfd == NULL) + { + nonfatal (output_filename); + } + copy_archive (ibfd, obfd, output_target); + } + else if (bfd_check_format_matches (ibfd, bfd_object, &matching)) { bfd *obfd = bfd_openw (output_filename, output_target); if (obfd == NULL) @@ -420,20 +430,15 @@ copy_file (input_filename, output_filename, input_target, output_target) nonfatal (input_filename); } } - else if (bfd_check_format (ibfd, bfd_archive)) - { - bfd *obfd = bfd_openw (output_filename, output_target); - if (obfd == NULL) - { - nonfatal (output_filename); - } - copy_archive (ibfd, obfd, output_target); - } else { - /* Get the right error message. */ - bfd_check_format (ibfd, bfd_object); - nonfatal (input_filename); + bfd_nonfatal (input_filename); + if (bfd_error == file_ambiguously_recognized) + { + list_matching_formats (matching); + free (matching); + } + status = 1; } } diff --git a/binutils/objdump.c b/binutils/objdump.c index 469bfbde7c..06a66af680 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -52,12 +52,13 @@ boolean disassemble; /* -d */ boolean formats_info; /* -i */ char *only; /* -j secname */ +/* Extra info to pass to the disassembler address printing function. */ struct objdump_disasm_info { bfd *abfd; asection *sec; }; -/* Architecture to disassemble for. */ +/* Architecture to disassemble for, or default if NULL. */ char *machine = (char *) NULL; /* The symbol table. */ @@ -414,13 +415,9 @@ void disassemble_data (abfd) bfd *abfd; { - bfd_byte *data = NULL; - bfd_arch_info_type *info; - bfd_size_type datasize = 0; bfd_size_type i; - unsigned int (*print) ()= 0; /* Old style */ + unsigned int (*print) () = 0; /* Old style */ disassembler_ftype disassemble = 0; /* New style */ - enum bfd_architecture a; struct disassemble_info disasm_info; struct objdump_disasm_info aux; @@ -429,14 +426,9 @@ disassemble_data (abfd) asection *section; - /* Replace symbol section relative values with abs values */ boolean done_dot = false; - INIT_DISASSEMBLE_INFO(disasm_info, stdout); - disasm_info.application_data = (PTR) &aux; - aux.abfd = abfd; - disasm_info.print_address_func = objdump_print_address; - + /* Replace symbol section relative values with abs values. */ for (i = 0; i < symcount; i++) { syms[i]->value += syms[i]->section->vma; @@ -447,10 +439,15 @@ disassemble_data (abfd) /* Sort the symbols into section and symbol order */ qsort (syms, symcount, sizeof (asymbol *), compare_symbols); + INIT_DISASSEMBLE_INFO(disasm_info, stdout); + disasm_info.application_data = (PTR) &aux; + aux.abfd = abfd; + disasm_info.print_address_func = objdump_print_address; + if (machine != (char *) NULL) { - info = bfd_scan_arch (machine); - if (info == 0) + bfd_arch_info_type *info = bfd_scan_arch (machine); + if (info == NULL) { fprintf (stderr, "%s: Can't use supplied machine %s\n", program_name, @@ -460,7 +457,7 @@ disassemble_data (abfd) abfd->arch_info = info; } - /* See if we can disassemble using bfd */ + /* See if we can disassemble using bfd. */ if (abfd->arch_info->disassemble) { @@ -468,7 +465,7 @@ disassemble_data (abfd) } else { - a = bfd_get_arch (abfd); + enum bfd_architecture a = bfd_get_arch (abfd); switch (a) { /* If you add a case to this table, also add it to the @@ -556,7 +553,7 @@ disassemble_data (abfd) default: fprintf (stderr, "%s: Can't disassemble for architecture %s\n", program_name, - bfd_printable_arch_mach (bfd_get_arch (abfd), 0)); + bfd_printable_arch_mach (a, 0)); exit (1); } @@ -566,91 +563,92 @@ disassemble_data (abfd) section != (asection *) NULL; section = section->next) { + bfd_byte *data = NULL; + bfd_size_type datasize = 0; + + if (!(section->flags & SEC_LOAD)) + continue; + if (only != (char *) NULL && strcmp (only, section->name) != 0) + continue; + + printf ("Disassembly of section %s:\n", section->name); + + datasize = bfd_get_section_size_before_reloc (section); + if (datasize == 0) + continue; + + data = (bfd_byte *) xmalloc ((size_t) datasize); + + bfd_get_section_contents (abfd, section, data, 0, datasize); + aux.sec = section; - - if ((section->flags & SEC_LOAD) - && (only == (char *) NULL || strcmp (only, section->name) == 0)) + disasm_info.buffer = data; + disasm_info.buffer_vma = section->vma; + disasm_info.buffer_length = datasize; + i = 0; + while (i < disasm_info.buffer_length) { - printf ("Disassembly of section %s:\n", section->name); - - if (bfd_get_section_size_before_reloc (section) == 0) - continue; - - data = (bfd_byte *) xmalloc ((size_t) bfd_get_section_size_before_reloc (section)); - - datasize = bfd_get_section_size_before_reloc (section); - - bfd_get_section_contents (abfd, section, data, 0, bfd_get_section_size_before_reloc (section)); - - disasm_info.buffer = data; - disasm_info.buffer_vma = section->vma; - disasm_info.buffer_length = - bfd_get_section_size_before_reloc (section); - i = 0; - while (i < disasm_info.buffer_length) + if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && + data[i + 3] == 0) { - if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && - data[i + 3] == 0) + if (done_dot == false) { - if (done_dot == false) - { - printf ("...\n"); - done_dot = true; - } - i += 4; + printf ("...\n"); + done_dot = true; } - else + i += 4; + } + else + { + done_dot = false; + if (with_line_numbers) { - done_dot = false; - if (with_line_numbers) - { - CONST char *filename; - CONST char *functionname; - unsigned int line; + CONST char *filename; + CONST char *functionname; + unsigned int line; - if (bfd_find_nearest_line (abfd, - section, - syms, - section->vma + i, - &filename, - &functionname, - &line)) + if (bfd_find_nearest_line (abfd, + section, + syms, + section->vma + i, + &filename, + &functionname, + &line)) + { + if (functionname && *functionname + && strcmp(functionname, prev_function)) { - if (functionname && *functionname - && strcmp(functionname, prev_function)) - { - printf ("%s():\n", functionname); - prev_function = functionname; - } - if (!filename) - filename = "???"; - if (line && line != prevline) - { - printf ("%s:%u\n", filename, line); - prevline = line; - } + printf ("%s():\n", functionname); + prev_function = functionname; + } + if (!filename) + filename = "???"; + if (line && line != prevline) + { + printf ("%s:%u\n", filename, line); + prevline = line; } } - objdump_print_address (section->vma + i, &disasm_info); - printf (" "); - - if (disassemble) /* New style */ - { - int bytes = (*disassemble)(section->vma + i, - &disasm_info); - if (bytes < 0) - break; - i += bytes; - } - else /* Old style */ - i += print (section->vma + i, - data + i, - stdout); - putchar ('\n'); } + objdump_print_address (section->vma + i, &disasm_info); + putchar (' '); + + if (disassemble) /* New style */ + { + int bytes = (*disassemble)(section->vma + i, + &disasm_info); + if (bytes < 0) + break; + i += bytes; + } + else /* Old style */ + i += print (section->vma + i, + data + i, + stdout); + putchar ('\n'); } - free (data); } + free (data); } } @@ -745,7 +743,7 @@ dump_stabs_1 (abfd, name1, name2) if (is_elf ? (0 == stabstr_hdr) : (0 == stabstrsect)) { fprintf (stderr, "%s: %s has no %s section\n", program_name, - abfd->filename, name2); + bfd_get_filename (abfd), name2); return; } @@ -763,7 +761,7 @@ dump_stabs_1 (abfd, name1, name2) { fprintf (stderr, "%s: Reading %s section of %s failed\n", program_name, name1, - abfd->filename); + bfd_get_filename (abfd)); return; } } @@ -779,7 +777,7 @@ dump_stabs_1 (abfd, name1, name2) { fprintf (stderr, "%s: Reading %s section of %s failed\n", program_name, name2, - abfd->filename); + bfd_get_filename (abfd)); return; } } @@ -872,16 +870,6 @@ dump_bfd_header (abfd) printf_vma (abfd->start_address); } -static void -list_matching_formats (p) - char **p; -{ - fprintf(stderr, "%s: Matching formats:", program_name); - while (*p) - fprintf(stderr, " %s", *p++); - fprintf(stderr, "\n"); -} - static void display_bfd (abfd) bfd *abfd; @@ -890,8 +878,7 @@ display_bfd (abfd) if (!bfd_check_format_matches (abfd, bfd_object, &matching)) { - fprintf (stderr, "%s: %s: %s\n", program_name, abfd->filename, - bfd_errmsg (bfd_error)); + bfd_nonfatal (bfd_get_filename (abfd)); if (bfd_error == file_ambiguously_recognized) { list_matching_formats (matching); @@ -900,7 +887,8 @@ display_bfd (abfd) return; } - printf ("\n%s: file format %s\n", abfd->filename, abfd->xvec->name); + printf ("\n%s: file format %s\n", bfd_get_filename (abfd), + abfd->xvec->name); if (dump_ar_hdrs) print_arelt_descr (stdout, abfd, true); if (dump_file_header) @@ -936,8 +924,7 @@ display_file (filename, target) file = bfd_openr (filename, target); if (file == NULL) { - fprintf (stderr, "%s: ", program_name); - bfd_perror (filename); + bfd_nonfatal (filename); return; } @@ -953,8 +940,7 @@ display_file (filename, target) { if (bfd_error != no_more_archived_files) { - fprintf (stderr, "%s: ", program_name); - bfd_perror (bfd_get_filename (file)); + bfd_nonfatal (bfd_get_filename (file)); } return; } @@ -1197,8 +1183,7 @@ display_target_list () tragic consequences that would otherwise ensue. */ if (abfd == NULL) { - fprintf (stderr, "%s: ", program_name); - bfd_perror (_DUMMY_NAME_); + bfd_nonfatal (_DUMMY_NAME_); return; } bfd_set_format (abfd, bfd_object); @@ -1242,8 +1227,7 @@ display_info_table (first, last) /* Just in case the open failed somehow. */ if (abfd == NULL) { - fprintf (stderr, "%s: ", program_name); - bfd_perror (_DUMMY_NAME_); + bfd_nonfatal (_DUMMY_NAME_); return; } bfd_set_format (abfd, bfd_object); diff --git a/binutils/size.c b/binutils/size.c index 2c587bb05d..eeff86e704 100644 --- a/binutils/size.c +++ b/binutils/size.c @@ -1,5 +1,5 @@ /* size.c -- report size of various sections of an executable file. - Copyright 1991, 1992 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 02139, 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 --compatibility or --pedantic 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)); +static void print_sizes PARAMS ((bfd * file)); + +static void berkeley_sum PARAMS ((bfd *, sec_ptr, PTR)); -/** main and like trivia */ - 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", stderr); + fputs ("default is --format=berkeley\n", stream); #else - fputs (" (default is --format=sysv)\n", stderr); + 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(); + 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(); - } + 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; + + print_sizes (abfd); + fputs (" (core file", stdout); + + 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); + } - puts(")"); - goto done; - } - - printf("Unknown file format: %s.", bfd_get_filename(abfd)); return_code = 3; - - done: - - - printf("\n"); - return; } static void -display_file(filename) - char *filename; +display_archive (file) + 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; + bfd_size_type total; - - if ((textsection = bfd_get_section_by_name (abfd, text_section_name)) - != NULL) { - textsize = bfd_get_section_size_before_reloc (textsection); - } + bsssize = 0; + datasize = 0; + textsize = 0; - 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_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\tdata\tbss/stk\toct\thex\tfilename" : - "text\tdata\tbss/stk\tdec\thex\tfilename"); +#if 0 + /* Intel doesn't like bss/stk because they don't have core files. */ + puts ((radix == octal) ? "text\tdata\tbss/stk\toct\thex\tfilename" : + "text\tdata\tbss/stk\tdec\thex\tfilename"); #else - puts((radix == octal) ? "text\tdata\tbss\toct\thex\tfilename" : - "text\tdata\tbss\tdec\thex\tfilename"); + puts ((radix == octal) ? "text\tdata\tbss\toct\thex\tfilename" : + "text\tdata\tbss\tdec\thex\tfilename"); #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(":\nsection\t\tsize\t addr"); - bfd_map_over_sections (file, sysv_internal_printer, (PTR)NULL); + puts (":\nsection\t\tsize\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); } diff --git a/binutils/strings.c b/binutils/strings.c index 9f52ee5393..02ef67ba37 100644 --- a/binutils/strings.c +++ b/binutils/strings.c @@ -1,5 +1,5 @@ /* strings -- print the strings of printable characters in files - Copyright (C) 1993 Free Software Foundation, Inc. + Copyright (C) 1993, 94 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,6 +37,9 @@ -o Like -to. (Some other implementations have -o like -to, others like -td. We chose one arbitrarily.) + --target=BFDNAME + Specify a non-default object file format. + --help -h Print the usage message on the standard output. @@ -84,12 +87,8 @@ static boolean datasection_only; /* true if we found an initialized data section in the current file. */ static boolean got_a_section; -/* Opened to /dev/null for reading from a BFD. - This is a kludge to avoid rewriting print_strings; - the way we call print_strings now, it actually only needs - to read from either a memory buffer or a stream, never both - for a given file. */ -static FILE *devnull; +/* The BFD object file format. */ +static char *target; extern char *program_version; @@ -99,6 +98,7 @@ static struct option long_options[] = {"print-file-name", no_argument, NULL, 'f'}, {"bytes", required_argument, NULL, 'n'}, {"radix", required_argument, NULL, 't'}, + {"target", required_argument, NULL, 'T'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {NULL, 0, NULL, 0} @@ -125,6 +125,7 @@ main (argc, argv) print_addresses = false; print_filenames = false; datasection_only = true; + target = NULL; while ((optc = getopt_long (argc, argv, "afn:ot:v0123456789", long_options, (int *) 0)) != EOF) @@ -180,6 +181,10 @@ main (argc, argv) } break; + case 'T': + target = optarg; + break; + case 'v': printf ("GNU %s version %s\n", program_name, program_version); exit (0); @@ -200,13 +205,6 @@ main (argc, argv) string_min = 4; bfd_init (); - devnull = fopen ("/dev/null", "r"); - if (devnull == NULL) - { - fprintf (stderr, "%s: ", program_name); - perror ("/dev/null"); - exit (1); - } for (; optind < argc; ++optind) { @@ -242,7 +240,7 @@ strings_a_section (abfd, sect, file) if (bfd_get_section_contents (abfd, sect, mem, (file_ptr) 0, sz)) { got_a_section = true; - print_strings (file, devnull, sect->filepos, 0, sz, mem); + print_strings (file, (FILE *) NULL, sect->filepos, 0, sz, mem); } free (mem); } @@ -250,6 +248,7 @@ strings_a_section (abfd, sect, file) /* Scan all of the sections in FILE, and print the strings in the initialized data section(s). + Return true if successful, false if not (such as if FILE is not an object file). */ @@ -257,31 +256,29 @@ static boolean strings_object_file (file) char *file; { - bfd *abfd = bfd_openr (file, NULL); + bfd *abfd = bfd_openr (file, target); if (abfd == NULL) { - if (bfd_error != system_call_error) - { - /* Out of memory, or an invalid target is specified by the - GNUTARGET environment variable. */ - fprintf (stderr, "%s: ", program_name); - bfd_perror (file); - } + /* Treat the file as a non-object file. */ return false; } - /* For some reason, without this call, the BFD has no sections. - This call is only for the side effect of reading in the sections. */ - bfd_check_format (abfd, bfd_object); + /* This call is mainly for its side effect of reading in the sections. + We follow the traditional behavior of `strings' in that we don't + complain if we don't recognize a file to be an object file. */ + if (bfd_check_format (abfd, bfd_object) == false) + { + bfd_close (abfd); + return false; + } got_a_section = false; bfd_map_over_sections (abfd, strings_a_section, file); if (!bfd_close (abfd)) { - fprintf (stderr, "%s: ", program_name); - bfd_perror (file); + bfd_nonfatal (file); return false; } @@ -328,7 +325,8 @@ strings_file (file) is at address ADDRESS in the file. Stop reading at address STOP_POINT in the file, if nonzero. - Optionally the caller can supply a buffer of characters + If STREAM is NULL, do not read from it. + The caller can supply a buffer of characters to be processed before the data in STREAM. MAGIC is the address of the buffer and MAGICCOUNT is how many characters are in it. @@ -364,6 +362,8 @@ print_strings (filename, stream, address, stop_point, magiccount, magic) } else { + if (stream == NULL) + return; c = getc (stream); if (c < 0) return; @@ -391,6 +391,8 @@ print_strings (filename, stream, address, stop_point, magiccount, magic) } else { + if (stream == NULL) + return; c = getc (stream); if (c < 0) return; @@ -412,15 +414,15 @@ print_strings (filename, stream, address, stop_point, magiccount, magic) switch (address_radix) { case 8: - printf ("%7lo ", address - i - 1); + printf ("%7lo ", (unsigned long) (address - i - 1)); break; case 10: - printf ("%7ld ", address - i - 1); + printf ("%7ld ", (long) (address - i - 1)); break; case 16: - printf ("%7lx ", address - i - 1); + printf ("%7lx ", (unsigned long) (address - i - 1)); break; } @@ -505,7 +507,7 @@ usage (stream, status) fprintf (stream, "\ Usage: %s [-afov] [-n min-len] [-min-len] [-t {o,x,d}] [-]\n\ [--all] [--print-file-name] [--bytes=min-len] [--radix={o,x,d}]\n\ - [--help] [--version] file...\n", + [--target=bfdname] [--help] [--version] file...\n", program_name); exit (status); }