* objcopy.c (filter_bytes): New function.

(copy_section): Call it.
	(copy_options, copy_usage, copy_main): Add --byte option to
	activate it.  Appropriate the -b option (which was an undocumented
	synonym for -F) for it, also.  Add --interleave, -i option for
	additional control.
	(setup_section, copy_section, mangle_section): Renamed with no `s'
	on the end.
	* objcopy.1, binutils.texi: Document the new options.

	* objdump.c (display_target_tables, display_target_list):
	New functions broken out of display_info.
	Eliminate some magic constants.  Use more meaningful variable names.
	(dump_bfd_header): New function broken out of display_bfd.
	(dump_section_header): New function broken out of dump_headers.
	(remove_useless_symbols): Don't shadow global variable name with
	parameter.
	(objdump_print_address): Fix backward test.
This commit is contained in:
David MacKenzie
1994-01-26 22:11:18 +00:00
parent d6d4e4c3d0
commit f7b839f7cd
5 changed files with 425 additions and 284 deletions

View File

@@ -1,3 +1,24 @@
Wed Jan 26 13:13:18 1994 David J. Mackenzie (djm@thepub.cygnus.com)
* objcopy.c (filter_bytes): New function.
(copy_section): Call it.
(copy_options, copy_usage, copy_main): Add --byte option to
activate it. Appropriate the -b option (which was an undocumented
synonym for -F) for it, also. Add --interleave, -i option for
additional control.
(setup_section, copy_section, mangle_section): Renamed with no `s'
on the end.
* objcopy.1, binutils.texi: Document the new options.
* objdump.c (display_target_tables, display_target_list):
New functions broken out of display_info.
Eliminate some magic constants. Use more meaningful variable names.
(dump_bfd_header): New function broken out of display_bfd.
(dump_section_header): New function broken out of dump_headers.
(remove_useless_symbols): Don't shadow global variable name with
parameter.
(objdump_print_address): Fix backward test.
Tue Jan 25 19:40:54 1994 Stan Shebs (shebs@andros.cygnus.com) Tue Jan 25 19:40:54 1994 Stan Shebs (shebs@andros.cygnus.com)
* bucomm.c (print_arelt_descr): Change decl of `when' to time_t. * bucomm.c (print_arelt_descr): Change decl of `when' to time_t.

View File

@@ -731,8 +731,9 @@ objcopy [ -F @var{bfdname} | --target=@var{bfdname} ]
[ -O @var{bfdname} | --output-target=@var{bfdname} ] [ -O @var{bfdname} | --output-target=@var{bfdname} ]
[ -S | --strip-all ] [ -g | --strip-debug ] [ -S | --strip-all ] [ -g | --strip-debug ]
[ -x | --discard-all ] [ -X | --discard-locals ] [ -x | --discard-all ] [ -X | --discard-locals ]
[ -b @var{byte} | --byte=@var{byte} ] [ -v | --verbose ] [ -b @var{byte} | --byte=@var{byte} ]
[ -V | --version ] [ --help ] [ -i @var{interleave} | --interleave=@var{interleave} ]
[ -v | --verbose ] [ -V | --version ] [ --help ]
@var{infile} [@var{outfile}] @var{infile} [@var{outfile}]
@end smallexample @end smallexample
@@ -793,9 +794,17 @@ Do not copy compiler-generated local symbols.
@item -b @var{byte} @item -b @var{byte}
@itemx --byte=@var{byte} @itemx --byte=@var{byte}
Keep only every @var{byte}th byte of the input file (header data is not Keep only every @var{byte}th byte of the input file (header data is not
affected). @var{byte} can be in the range from 0 to 3. This option is affected). @var{byte} can be in the range from 0 to @var{interleave}-1,
useful for creating files to program 4 ROMs to create 32-bit words. It where @var{interleave} is given by the @samp{-i} or @samp{--interleave}
is typically used with an @code{srec} output target. option, or the default of 4. This option is useful for creating files
to program ROMs. It is typically used with an @code{srec} output
target.
@item -i @var{interleave}
@itemx --interleave=@var{interleave}
Only copy one out of every @var{interleave} bytes. Which one to copy is
selected by the @var{-b} or @samp{--byte} option. The default is 4.
The interleave is ignored if neither @samp{-b} nor @samp{--byte} is given.
@item -V @item -V
@itemx --version @itemx --version

View File

@@ -8,7 +8,7 @@
.. ..
.SH NAME .SH NAME
objcopy\(em\&copy and translate object files objcopy \- copy and translate object files
.SH SYNOPSIS .SH SYNOPSIS
.hy 0 .hy 0
@@ -22,6 +22,8 @@ objcopy\(em\&copy and translate object files
.RB "[\|" \-g\ |\ \-\-strip\-debug\fR "\|]" .RB "[\|" \-g\ |\ \-\-strip\-debug\fR "\|]"
.RB "[\|" \-x\ |\ \-\-discard\-all\fR "\|]" .RB "[\|" \-x\ |\ \-\-discard\-all\fR "\|]"
.RB "[\|" \-X\ |\ \-\-discard\-locals\fR "\|]" .RB "[\|" \-X\ |\ \-\-discard\-locals\fR "\|]"
.RB "[\|" \-b\ \fIbyte\fP |\ \-\-byte=\fIbyte\fP "\|]"
.RB "[\|" \-i\ \fIinterleave\fP |\ \-\-interleave=\fIinterleave\fP "\|]"
.RB "[\|" \-v\ |\ \-\-verbose\fR "\|]" .RB "[\|" \-v\ |\ \-\-verbose\fR "\|]"
.RB "[\|" \-V\ |\ \-\-version\fR "\|]" .RB "[\|" \-V\ |\ \-\-version\fR "\|]"
.RB "[\|" \-\-help\fR "\|]" .RB "[\|" \-\-help\fR "\|]"
@@ -85,6 +87,17 @@ Do not copy non-global symbols from the source file.
Do not copy compiler-generated local symbols. (These usually start Do not copy compiler-generated local symbols. (These usually start
with "L" or "."). with "L" or ".").
.TP .TP
.B \-b \fIbyte\fR, \fB\-\-byte=\fIbyte
Keep only every \fIbyte\fPth byte of the input file (header data is
not affected). \fIbyte\fP can be in the range from 0 to the
interleave-1. This option is useful for creating files to program
ROMs. It is typically used with an srec output target.
.TP
.B \-i \fIinterleave\fR, \fB\-\-interleave=\fIinterleave
Only copy one out of every \fIinterleave\fP bytes. Which one to copy is
selected by the \fB\-b\fP or \fB\-\-byte\fP option. The default is 4.
The interleave is ignored if neither \fB\-b\fP nor \fB\-\-byte\fP is given.
.TP
.B \-v\fR, \fB\-\-verbose .B \-v\fR, \fB\-\-verbose
Verbose output: list all object files modified. In the case of Verbose output: list all object files modified. In the case of
archives, "\fBobjcopy \-V\fR" lists all members of the archive. archives, "\fBobjcopy \-V\fR" lists all members of the archive.

View File

@@ -1,5 +1,5 @@
/* objcopy.c -- copy object file from input to output, optionally massaging it. /* objcopy.c -- copy object file from input to output, optionally massaging it.
Copyright (C) 1991 Free Software Foundation, Inc. Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
This file is part of GNU Binutils. This file is part of GNU Binutils.
@@ -22,16 +22,21 @@
#include "bucomm.h" #include "bucomm.h"
#include <getopt.h> #include <getopt.h>
static void setup_sections (); static void setup_section ();
static void copy_sections (); static void copy_section ();
static void mangle_sections (); static void mangle_section ();
#define nonfatal(s) {bfd_nonfatal(s); status = 1; return;} #define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
static asymbol **isympp = NULL; /* Input symbols */ static asymbol **isympp = NULL; /* Input symbols */
static asymbol **osympp = NULL; /* Output symbols that survive stripping */ static asymbol **osympp = NULL; /* Output symbols that survive stripping */
/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */
static int copy_byte = -1;
static int interleave = 4;
static boolean verbose; /* Print file and target names. */ static boolean verbose; /* Print file and target names. */
static int status = 0; static int status = 0; /* Exit status. */
enum strip_action enum strip_action
{ {
@@ -58,20 +63,19 @@ static enum locals_action discard_locals;
static struct option strip_options[] = static struct option strip_options[] =
{ {
{"strip-all", no_argument, 0, 's'},
{"strip-debug", no_argument, 0, 'S'},
{"discard-all", no_argument, 0, 'x'}, {"discard-all", no_argument, 0, 'x'},
{"discard-locals", no_argument, 0, 'X'}, {"discard-locals", no_argument, 0, 'X'},
{"help", no_argument, 0, 'h'},
{"input-target", required_argument, 0, 'I'},
{"input-format", required_argument, 0, 'I'}, /* Obsolete */
{"output-target", required_argument, 0, 'O'},
{"output-format", required_argument, 0, 'O'}, /* Obsolete */
{"target", required_argument, 0, 'F'},
{"format", required_argument, 0, 'F'}, /* Obsolete */ {"format", required_argument, 0, 'F'}, /* Obsolete */
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'}, {"input-format", required_argument, 0, 'I'}, /* Obsolete */
{"input-target", required_argument, 0, 'I'},
{"output-format", required_argument, 0, 'O'}, /* Obsolete */
{"output-target", required_argument, 0, 'O'},
{"strip-all", no_argument, 0, 's'},
{"strip-debug", no_argument, 0, 'S'},
{"target", required_argument, 0, 'F'},
{"verbose", no_argument, 0, 'v'}, {"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{0, no_argument, 0, 0} {0, no_argument, 0, 0}
}; };
@@ -79,20 +83,21 @@ static struct option strip_options[] =
static struct option copy_options[] = static struct option copy_options[] =
{ {
{"strip-all", no_argument, 0, 'S'}, {"byte", required_argument, 0, 'b'},
{"strip-debug", no_argument, 0, 'g'},
{"discard-all", no_argument, 0, 'x'}, {"discard-all", no_argument, 0, 'x'},
{"discard-locals", no_argument, 0, 'X'}, {"discard-locals", no_argument, 0, 'X'},
{"help", no_argument, 0, 'h'},
{"input-target", required_argument, 0, 'I'},
{"input-format", required_argument, 0, 'I'}, /* Obsolete */
{"output-target", required_argument, 0, 'O'},
{"output-format", required_argument, 0, 'O'}, /* Obsolete */
{"target", required_argument, 0, 'F'},
{"format", required_argument, 0, 'F'}, /* Obsolete */ {"format", required_argument, 0, 'F'}, /* Obsolete */
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'}, {"input-format", required_argument, 0, 'I'}, /* Obsolete */
{"input-target", required_argument, 0, 'I'},
{"interleave", required_argument, 0, 'i'},
{"output-format", required_argument, 0, 'O'}, /* Obsolete */
{"output-target", required_argument, 0, 'O'},
{"strip-all", no_argument, 0, 'S'},
{"strip-debug", no_argument, 0, 'g'},
{"target", required_argument, 0, 'F'},
{"verbose", no_argument, 0, 'v'}, {"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{0, no_argument, 0, 0} {0, no_argument, 0, 0}
}; };
@@ -112,10 +117,12 @@ copy_usage (stream, status)
int status; int status;
{ {
fprintf (stream, "\ fprintf (stream, "\
Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname]\n\ Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
[-i interleave] [--interleave=interleave] [--byte=byte]\n\
[--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
[--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\ [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
[--verbose] [--version] [--help] in-file [out-file]\n", program_name); [--verbose] [--version] [--help] in-file [out-file]\n",
program_name);
exit (status); exit (status);
} }
@@ -200,6 +207,21 @@ filter_symbols (abfd, osyms, isyms, symcount)
return dst_count; return dst_count;
} }
/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
Adjust *SIZE. */
void
filter_bytes (memhunk, size)
PTR memhunk;
bfd_size_type *size;
{
char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
for (; from < end; from += interleave)
*to++ = *from;
*size /= interleave;
}
/* Copy object file IBFD onto OBFD. */ /* Copy object file IBFD onto OBFD. */
static void static void
@@ -266,9 +288,9 @@ copy_object (ibfd, obfd)
/* bfd mandates that all output sections be created and sizes set before /* bfd mandates that all output sections be created and sizes set before
any output is done. Thus, we traverse all sections multiple times. */ any output is done. Thus, we traverse all sections multiple times. */
bfd_map_over_sections (ibfd, setup_sections, (void *) obfd); bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
bfd_map_over_sections (ibfd, copy_sections, (void *) obfd); bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
bfd_map_over_sections (ibfd, mangle_sections, (void *) obfd); bfd_map_over_sections (ibfd, mangle_section, (void *) obfd);
} }
static char * static char *
@@ -419,7 +441,7 @@ copy_file (input_filename, output_filename, input_target, output_target)
as ISECTION in IBFD. */ as ISECTION in IBFD. */
static void static void
setup_sections (ibfd, isection, obfd) setup_section (ibfd, isection, obfd)
bfd *ibfd; bfd *ibfd;
sec_ptr isection; sec_ptr isection;
bfd *obfd; bfd *obfd;
@@ -493,7 +515,7 @@ loser:
If stripping then don't copy any relocation info. */ If stripping then don't copy any relocation info. */
static void static void
copy_sections (ibfd, isection, obfd) copy_section (ibfd, isection, obfd)
bfd *ibfd; bfd *ibfd;
sec_ptr isection; sec_ptr isection;
bfd *obfd; bfd *obfd;
@@ -544,6 +566,9 @@ copy_sections (ibfd, isection, obfd)
nonfatal (bfd_get_filename (ibfd)); nonfatal (bfd_get_filename (ibfd));
} }
if (copy_byte >= 0)
filter_bytes (memhunk, &size);
if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0, if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
size)) size))
{ {
@@ -559,7 +584,7 @@ copy_sections (ibfd, isection, obfd)
their new location in the output file, through some complex sums. */ their new location in the output file, through some complex sums. */
static void static void
mangle_sections (ibfd, p, obfd) mangle_section (ibfd, p, obfd)
bfd *ibfd; bfd *ibfd;
asection *p; asection *p;
bfd *obfd; bfd *obfd;
@@ -747,11 +772,29 @@ copy_main (argc, argv)
boolean show_version = false; boolean show_version = false;
int c; int c;
while ((c = getopt_long (argc, argv, "I:s:O:d:F:b:SgxXVv", while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:SgxXVv",
copy_options, (int *) 0)) != EOF) copy_options, (int *) 0)) != EOF)
{ {
switch (c) switch (c)
{ {
case 'b':
copy_byte = atoi(optarg);
if (copy_byte < 0)
{
fprintf (stderr, "%s: byte number must be non-negative\n",
program_name);
exit (1);
}
break;
case 'i':
interleave = atoi(optarg);
if (interleave < 1)
{
fprintf(stderr, "%s: interleave must be positive\n",
program_name);
exit (1);
}
break;
case 'I': case 'I':
case 's': /* "source" - 'I' is preferred */ case 's': /* "source" - 'I' is preferred */
input_target = optarg; input_target = optarg;
@@ -760,7 +803,6 @@ copy_main (argc, argv)
output_target = optarg; output_target = optarg;
break; break;
case 'F': case 'F':
case 'b': /* "both" - 'F' is preferred */
input_target = output_target = optarg; input_target = output_target = optarg;
break; break;
case 'S': case 'S':
@@ -796,6 +838,13 @@ copy_main (argc, argv)
exit (0); exit (0);
} }
if (copy_byte >= interleave)
{
fprintf (stderr, "%s: byte number must be less than interleave\n",
program_name);
exit (1);
}
if (optind == argc || optind + 2 < argc) if (optind == argc || optind + 2 < argc)
copy_usage (stderr, 1); copy_usage (stderr, 1);

View File

@@ -57,11 +57,16 @@ struct objdump_disasm_info {
asection *sec; asection *sec;
}; };
/* Architecture to disassemble for. */
char *machine = (char *) NULL; char *machine = (char *) NULL;
/* The symbol table. */
asymbol **syms; asymbol **syms;
/* Number of bytes allocated for `syms'. */
unsigned int storage; unsigned int storage;
/* Number of symbols in `syms'. */
unsigned int symcount = 0; unsigned int symcount = 0;
/* Forward declarations. */ /* Forward declarations. */
@@ -118,52 +123,53 @@ static struct option long_options[]=
{"version", no_argument, &show_version, 1}, {"version", no_argument, &show_version, 1},
{0, no_argument, 0, 0} {0, no_argument, 0, 0}
}; };
static void
dump_section_header (abfd, section, ignored)
bfd *abfd;
asection *section;
PTR ignored;
{
char *comma = "";
#define PF(x,y) \
if (section->flags & x) { printf("%s%s",comma,y); comma = ", "; }
printf ("SECTION %d [%s]\t: size %08x",
section->index,
section->name,
(unsigned) bfd_get_section_size_before_reloc (section));
printf (" vma ");
printf_vma (section->vma);
printf (" align 2**%u\n ",
section->alignment_power);
PF (SEC_ALLOC, "ALLOC");
PF (SEC_CONSTRUCTOR, "CONSTRUCTOR");
PF (SEC_CONSTRUCTOR_TEXT, "CONSTRUCTOR TEXT");
PF (SEC_CONSTRUCTOR_DATA, "CONSTRUCTOR DATA");
PF (SEC_CONSTRUCTOR_BSS, "CONSTRUCTOR BSS");
PF (SEC_LOAD, "LOAD");
PF (SEC_RELOC, "RELOC");
#ifdef SEC_BALIGN
PF (SEC_BALIGN, "BALIGN");
#endif
PF (SEC_READONLY, "READONLY");
PF (SEC_CODE, "CODE");
PF (SEC_DATA, "DATA");
PF (SEC_ROM, "ROM");
PF (SEC_DEBUGGING, "DEBUGGING");
printf ("\n");
#undef PF
}
static void static void
dump_headers (abfd) dump_headers (abfd)
bfd *abfd; bfd *abfd;
{ {
asection *section; bfd_map_over_sections (abfd, dump_section_header, (PTR) NULL);
for (section = abfd->sections;
section != (asection *) NULL;
section = section->next)
{
char *comma = "";
#define PF(x,y) \
if (section->flags & x) { printf("%s%s",comma,y); comma = ", "; }
printf ("SECTION %d [%s]\t: size %08x",
section->index,
section->name,
(unsigned) bfd_get_section_size_before_reloc (section));
printf (" vma ");
printf_vma (section->vma);
printf (" align 2**%u\n ",
section->alignment_power);
PF (SEC_ALLOC, "ALLOC");
PF (SEC_CONSTRUCTOR, "CONSTRUCTOR");
PF (SEC_CONSTRUCTOR_TEXT, "CONSTRUCTOR TEXT");
PF (SEC_CONSTRUCTOR_DATA, "CONSTRUCTOR DATA");
PF (SEC_CONSTRUCTOR_BSS, "CONSTRUCTOR BSS");
PF (SEC_LOAD, "LOAD");
PF (SEC_RELOC, "RELOC");
#ifdef SEC_BALIGN
PF (SEC_BALIGN, "BALIGN");
#endif
PF (SEC_READONLY, "READONLY");
PF (SEC_CODE, "CODE");
PF (SEC_DATA, "DATA");
PF (SEC_ROM, "ROM");
PF (SEC_DEBUGGING, "DEBUGGING");
printf ("\n");
#undef PF
}
} }
static asymbol ** static asymbol **
slurp_symtab (abfd) slurp_symtab (abfd)
bfd *abfd; bfd *abfd;
@@ -172,8 +178,8 @@ slurp_symtab (abfd)
if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
{ {
(void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd)); printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd));
return (NULL); return NULL;
} }
storage = get_symtab_upper_bound (abfd); storage = get_symtab_upper_bound (abfd);
@@ -191,17 +197,18 @@ slurp_symtab (abfd)
return sy; return sy;
} }
/* Filter out (in place) symbols that are useless for dis-assemble. /* Filter out (in place) symbols that are useless for disassembly.
Return count of useful symbols. */ COUNT is the number of elements in SYMBOLS.
Return the number of useful symbols. */
int remove_useless_symbols (syms, count) int
asymbol **syms; remove_useless_symbols (symbols, count)
asymbol **symbols;
int count; int count;
{ {
register asymbol **in_ptr = syms; register asymbol **in_ptr = symbols, **out_ptr = symbols;
register asymbol **out_ptr = syms;
while ( --count >= 0 ) while (--count >= 0)
{ {
asymbol *sym = *in_ptr++; asymbol *sym = *in_ptr++;
@@ -215,10 +222,9 @@ int remove_useless_symbols (syms, count)
*out_ptr++ = sym; *out_ptr++ = sym;
} }
return out_ptr - syms; return out_ptr - symbols;
} }
/* Sort symbols into value order. */ /* Sort symbols into value order. */
static int static int
@@ -241,14 +247,13 @@ compare_symbols (ap, bp)
return 0; return 0;
} }
/* Print the supplied address symbolically if possible */ /* Print VMA symbolically to INFO if possible. */
void void
objdump_print_address (vma, info) objdump_print_address (vma, info)
bfd_vma vma; bfd_vma vma;
struct disassemble_info *info; struct disassemble_info *info;
{ {
/* Perform a binary search looking for the closest symbol to
the required value. */
/* @@ For relocateable files, should filter out symbols belonging to /* @@ For relocateable files, should filter out symbols belonging to
the wrong section. Unfortunately, not enough information is supplied the wrong section. Unfortunately, not enough information is supplied
to this routine to determine the correct section in all cases. */ to this routine to determine the correct section in all cases. */
@@ -257,9 +262,9 @@ objdump_print_address (vma, info)
operand can be present at a time, so the 2-entry cache wouldn't be operand can be present at a time, so the 2-entry cache wouldn't be
constantly churned by code doing heavy memory accesses. */ constantly churned by code doing heavy memory accesses. */
/* Indices in `syms'. */
unsigned int min = 0; unsigned int min = 0;
unsigned int max = symcount; unsigned int max = symcount;
unsigned int thisplace = 1; unsigned int thisplace = 1;
unsigned int oldthisplace; unsigned int oldthisplace;
@@ -267,117 +272,125 @@ objdump_print_address (vma, info)
fprintf_vma (info->stream, vma); fprintf_vma (info->stream, vma);
if (symcount > 0) if (symcount < 1)
return;
/* Perform a binary search looking for the closest symbol to
the required value. */
while (true)
{ {
while (true) asymbol *sym;
{ #if 0
asymbol *sym; asection *sym_sec; asection *sym_sec;
oldthisplace = thisplace; #endif
thisplace = (max + min) / 2; oldthisplace = thisplace;
if (thisplace == oldthisplace) thisplace = (max + min) / 2;
break; if (thisplace == oldthisplace)
sym = syms[thisplace]; break;
vardiff = sym->value - vma; sym = syms[thisplace];
sym_sec = sym->section; vardiff = sym->value - vma;
#if 0
sym_sec = sym->section;
#endif
if (vardiff > 0) if (vardiff > 0)
max = thisplace; max = thisplace;
else if (vardiff < 0) else if (vardiff < 0)
min = thisplace; min = thisplace;
else else
goto found; goto found;
}
/* We've run out of places to look, print the symbol before this one
see if this or the symbol before describes this location the best */
if (thisplace != 0)
{
if (syms[thisplace - 1]->value - vma >
syms[thisplace]->value - vma)
{
/* Previous symbol is in correct section and is closer */
thisplace--;
}
}
found:
{
bfd_vma val = syms[thisplace]->value;
int i;
if (syms[thisplace]->flags & (BSF_LOCAL|BSF_DEBUGGING))
for (i = thisplace - 1; i >= 0; i--)
{
if (syms[i]->value == val
&& (!(syms[i]->flags & (BSF_LOCAL|BSF_DEBUGGING))
|| ((syms[thisplace]->flags & BSF_DEBUGGING)
&& !(syms[i]->flags & BSF_DEBUGGING))))
{
thisplace = i;
break;
}
}
if (syms[thisplace]->flags & (BSF_LOCAL|BSF_DEBUGGING))
for (i = thisplace + 1; i < symcount; i++)
{
if (syms[i]->value == val
&& (!(syms[i]->flags & (BSF_LOCAL|BSF_DEBUGGING))
|| ((syms[thisplace]->flags & BSF_DEBUGGING)
&& !(syms[i]->flags & BSF_DEBUGGING))))
{
thisplace = i;
break;
}
}
}
{
/* If the file is relocateable, and the symbol could be from this
section, prefer a symbol from this section over symbols from
others, even if the other symbol's value might be closer.
Note that this may be wrong for some symbol references if the
sections have overlapping memory ranges, but in that case there's
no way to tell what's desired without looking at the relocation
table. */
struct objdump_disasm_info *aux;
int i;
aux = (struct objdump_disasm_info *) info->application_data;
if (aux->abfd->flags & HAS_RELOC
&& vma >= bfd_get_section_vma (aux->abfd, aux->sec)
&& vma < (bfd_get_section_vma (aux->abfd, aux->sec)
+ bfd_get_section_size_before_reloc (aux->sec))
&& syms[thisplace]->section != aux->sec)
{
for (i = thisplace + 1; i < symcount; i++)
if (syms[i]->value != syms[thisplace]->value)
break;
while (--i >= 0)
if (syms[i]->section == aux->sec)
{
thisplace = i;
break;
}
}
}
fprintf (info->stream, " <%s", syms[thisplace]->name);
if (syms[thisplace]->value > vma)
{
char buf[30], *p = buf;
sprintf_vma (buf, syms[thisplace]->value - vma);
while (*p == '0')
p++;
fprintf (info->stream, "-%s", p);
}
else if (vma > syms[thisplace]->value)
{
char buf[30], *p = buf;
sprintf_vma (buf, vma - syms[thisplace]->value);
while (*p == '0')
p++;
fprintf (info->stream, "+%s", p);
}
fprintf (info->stream, ">");
} }
/* We've run out of places to look; see whether this or the
symbol before this describes this location the best. */
if (thisplace != 0)
{
if (syms[thisplace - 1]->value - vma < syms[thisplace]->value - vma)
{
/* Previous symbol is in correct section and is closer. */
thisplace--;
}
}
found:
{
/* If this symbol isn't global, search for one with the same value
that is. */
bfd_vma val = syms[thisplace]->value;
int i;
if (syms[thisplace]->flags & (BSF_LOCAL|BSF_DEBUGGING))
for (i = thisplace - 1; i >= 0; i--)
{
if (syms[i]->value == val
&& (!(syms[i]->flags & (BSF_LOCAL|BSF_DEBUGGING))
|| ((syms[thisplace]->flags & BSF_DEBUGGING)
&& !(syms[i]->flags & BSF_DEBUGGING))))
{
thisplace = i;
break;
}
}
if (syms[thisplace]->flags & (BSF_LOCAL|BSF_DEBUGGING))
for (i = thisplace + 1; i < symcount; i++)
{
if (syms[i]->value == val
&& (!(syms[i]->flags & (BSF_LOCAL|BSF_DEBUGGING))
|| ((syms[thisplace]->flags & BSF_DEBUGGING)
&& !(syms[i]->flags & BSF_DEBUGGING))))
{
thisplace = i;
break;
}
}
}
{
/* If the file is relocateable, and the symbol could be from this
section, prefer a symbol from this section over symbols from
others, even if the other symbol's value might be closer.
Note that this may be wrong for some symbol references if the
sections have overlapping memory ranges, but in that case there's
no way to tell what's desired without looking at the relocation
table. */
struct objdump_disasm_info *aux;
int i;
aux = (struct objdump_disasm_info *) info->application_data;
if ((aux->abfd->flags & HAS_RELOC)
&& vma >= bfd_get_section_vma (aux->abfd, aux->sec)
&& vma < (bfd_get_section_vma (aux->abfd, aux->sec)
+ bfd_get_section_size_before_reloc (aux->sec))
&& syms[thisplace]->section != aux->sec)
{
for (i = thisplace + 1; i < symcount; i++)
if (syms[i]->value != syms[thisplace]->value)
break;
while (--i >= 0)
if (syms[i]->section == aux->sec)
{
thisplace = i;
break;
}
}
}
fprintf (info->stream, " <%s", syms[thisplace]->name);
if (syms[thisplace]->value > vma)
{
char buf[30], *p = buf;
sprintf_vma (buf, syms[thisplace]->value - vma);
while (*p == '0')
p++;
fprintf (info->stream, "-%s", p);
}
else if (vma > syms[thisplace]->value)
{
char buf[30], *p = buf;
sprintf_vma (buf, vma - syms[thisplace]->value);
while (*p == '0')
p++;
fprintf (info->stream, "+%s", p);
}
fprintf (info->stream, ">");
} }
#ifdef ARCH_all #ifdef ARCH_all
@@ -432,7 +445,7 @@ disassemble_data (abfd)
symcount = remove_useless_symbols (syms, symcount); symcount = remove_useless_symbols (syms, symcount);
/* Sort the symbols into section and symbol order */ /* Sort the symbols into section and symbol order */
(void) qsort (syms, symcount, sizeof (asymbol *), compare_symbols); qsort (syms, symcount, sizeof (asymbol *), compare_symbols);
if (machine != (char *) NULL) if (machine != (char *) NULL)
{ {
@@ -834,7 +847,33 @@ dump_stabs_1 (abfd, name1, name2)
} }
static void static void
list_matching_formats(p) dump_bfd_header (abfd)
bfd *abfd;
{
char *comma = "";
printf ("architecture: %s, ",
bfd_printable_arch_mach (bfd_get_arch (abfd),
bfd_get_mach (abfd)));
printf ("flags 0x%08x:\n", abfd->flags);
#define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";}
PF (HAS_RELOC, "HAS_RELOC");
PF (EXEC_P, "EXEC_P");
PF (HAS_LINENO, "HAS_LINENO");
PF (HAS_DEBUG, "HAS_DEBUG");
PF (HAS_SYMS, "HAS_SYMS");
PF (HAS_LOCALS, "HAS_LOCALS");
PF (DYNAMIC, "DYNAMIC");
PF (WP_TEXT, "WP_TEXT");
PF (D_PAGED, "D_PAGED");
PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE");
printf ("\nstart address 0x");
printf_vma (abfd->start_address);
}
static void
list_matching_formats (p)
char **p; char **p;
{ {
fprintf(stderr, "%s: Matching formats:", program_name); fprintf(stderr, "%s: Matching formats:", program_name);
@@ -860,35 +899,13 @@ display_bfd (abfd)
} }
return; return;
} }
printf ("\n%s: file format %s\n", abfd->filename, abfd->xvec->name); printf ("\n%s: file format %s\n", abfd->filename, abfd->xvec->name);
if (dump_ar_hdrs) if (dump_ar_hdrs)
print_arelt_descr (stdout, abfd, true); print_arelt_descr (stdout, abfd, true);
if (dump_file_header) if (dump_file_header)
{ dump_bfd_header (abfd);
char *comma = ""; putchar ('\n');
printf ("architecture: %s, ",
bfd_printable_arch_mach (bfd_get_arch (abfd),
bfd_get_mach (abfd)));
printf ("flags 0x%08x:\n", abfd->flags);
#define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";}
PF (HAS_RELOC, "HAS_RELOC");
PF (EXEC_P, "EXEC_P");
PF (HAS_LINENO, "HAS_LINENO");
PF (HAS_DEBUG, "HAS_DEBUG");
PF (HAS_SYMS, "HAS_SYMS");
PF (HAS_LOCALS, "HAS_LOCALS");
PF (DYNAMIC, "DYNAMIC");
PF (WP_TEXT, "WP_TEXT");
PF (D_PAGED, "D_PAGED");
PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE");
printf ("\nstart address 0x");
printf_vma (abfd->start_address);
}
printf ("\n");
if (dump_section_headers) if (dump_section_headers)
dump_headers (abfd); dump_headers (abfd);
if (dump_symtab || dump_reloc_info || disassemble) if (dump_symtab || dump_reloc_info || disassemble)
@@ -1150,92 +1167,124 @@ dump_relocs (abfd)
} }
} }
/* A file to open each BFD on. It will never actually be written to. */
#ifdef unix #ifdef unix
#define _DUMMY_NAME_ "/dev/null" #define _DUMMY_NAME_ "/dev/null"
#else #else
#define _DUMMY_NAME_ "##dummy" #define _DUMMY_NAME_ "##dummy"
#endif #endif
/* The length of the longest architecture name + 1. */
#define LONGEST_ARCH sizeof("rs6000:6000")
/* List the targets that BFD is configured to support, each followed
by its endianness and the architectures it supports. */
static void
display_target_list ()
{
extern bfd_target *bfd_target_vector[];
int t;
for (t = 0; bfd_target_vector[t]; t++)
{
int a;
bfd_target *p = bfd_target_vector[t];
bfd *abfd = bfd_openw (_DUMMY_NAME_, p->name);
bfd_set_format (abfd, bfd_object);
printf ("%s\n (header %s, data %s)\n", p->name,
p->header_byteorder_big_p ? "big endian" : "little endian",
p->byteorder_big_p ? "big endian" : "little endian");
for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++)
if (bfd_set_arch_mach (abfd, (enum bfd_architecture) a, 0))
printf (" %s\n",
bfd_printable_arch_mach ((enum bfd_architecture) a, 0));
}
}
/* Print a table showing which architectures are supported for entries
FIRST through LAST-1 of bfd_target_vector (targets across,
architectures down). */
static void static void
display_info_table (first, last) display_info_table (first, last)
int first; int first;
int last; int last;
{ {
unsigned int i, j; int t, a;
extern bfd_target *bfd_target_vector[]; extern bfd_target *bfd_target_vector[];
printf ("\n%12s", " "); /* Print heading of target names. */
for (i = first; i++ < last && bfd_target_vector[i];) printf ("\n%*s", LONGEST_ARCH, " ");
printf ("%s ", bfd_target_vector[i]->name); for (t = first; t++ < last && bfd_target_vector[t];)
printf ("\n"); printf ("%s ", bfd_target_vector[t]->name);
putchar ('\n');
for (j = (int) bfd_arch_obscure + 1; (int) j < (int) bfd_arch_last; j++) for (a = (int) bfd_arch_obscure + 1; a < (int) bfd_arch_last; a++)
if (strcmp (bfd_printable_arch_mach (j, 0), "UNKNOWN!") != 0) if (strcmp (bfd_printable_arch_mach (a, 0), "UNKNOWN!") != 0)
{ {
printf ("%11s ", bfd_printable_arch_mach (j, 0)); printf ("%*s ", LONGEST_ARCH - 1, bfd_printable_arch_mach (a, 0));
for (i = first; i++ < last && bfd_target_vector[i];) for (t = first; t++ < last && bfd_target_vector[t];)
{ {
bfd_target *p = bfd_target_vector[i]; bfd_target *p = bfd_target_vector[t];
bfd *abfd = bfd_openw (_DUMMY_NAME_, p->name); bfd *abfd = bfd_openw (_DUMMY_NAME_, p->name);
int l = strlen (p->name);
int ok;
bfd_set_format (abfd, bfd_object);
ok = bfd_set_arch_mach (abfd, j, 0);
if (ok) bfd_set_format (abfd, bfd_object);
if (bfd_set_arch_mach (abfd, a, 0))
printf ("%s ", p->name); printf ("%s ", p->name);
else else
{ {
int l = strlen (p->name);
while (l--) while (l--)
printf ("%c", ok ? '*' : '-'); putchar ('-');
printf (" "); putchar (' ');
} }
} }
printf ("\n"); putchar ('\n');
} }
} }
/* Print tables of all the target-architecture combinations that
BFD has been configured to support. */
static void
display_target_tables ()
{
int t, columns;
extern bfd_target *bfd_target_vector[];
char *colum;
extern char *getenv ();
columns = 0;
colum = getenv ("COLUMNS");
if (colum != NULL)
columns = atoi (colum);
if (columns == 0)
columns = 80;
for (t = 0; bfd_target_vector[t];)
{
int oldt = t, wid;
for (wid = LONGEST_ARCH; bfd_target_vector[t] && wid < columns; t++)
wid += strlen (bfd_target_vector[t]->name) + 1;
t--;
if (oldt == t)
break;
display_info_table (oldt, t);
}
}
static void static void
display_info () display_info ()
{ {
char *colum;
unsigned int i, j, columns;
extern bfd_target *bfd_target_vector[];
extern char *getenv ();
printf ("BFD header file version %s\n", BFD_VERSION); printf ("BFD header file version %s\n", BFD_VERSION);
for (i = 0; bfd_target_vector[i]; i++) display_target_list ();
{ display_target_tables ();
bfd_target *p = bfd_target_vector[i];
bfd *abfd = bfd_openw (_DUMMY_NAME_, p->name);
bfd_set_format (abfd, bfd_object);
printf ("%s\n (header %s, data %s)\n", p->name,
p->header_byteorder_big_p ? "big endian" : "little endian",
p->byteorder_big_p ? "big endian" : "little endian");
for (j = (int) bfd_arch_obscure + 1; j < (int) bfd_arch_last; j++)
if (bfd_set_arch_mach (abfd, (enum bfd_architecture) j, 0))
printf (" %s\n",
bfd_printable_arch_mach ((enum bfd_architecture) j, 0));
}
columns = 0;
if ((colum = getenv ("COLUMNS")) != (char *) NULL)
columns = atoi (colum);
if (!columns)
columns = 80;
for (i = 0; bfd_target_vector[i];)
{
int old;
old = i;
for (j = 12; bfd_target_vector[i] && j < columns; i++)
j += strlen (bfd_target_vector[i]->name) + 1;
i--;
if (old == i)
break;
display_info_table (old, i);
}
} }
/** main and like trivia */
int int
main (argc, argv) main (argc, argv)
int argc; int argc;