/* objdump.c -- dump information about an object file.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004
+ 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GNU Binutils.
static bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */
static int dump_debugging; /* --debugging */
static int dump_debugging_tags; /* --debugging-tags */
+static int dump_special_syms = 0; /* --special-syms */
static bfd_vma adjust_section_vma = 0; /* --adjust-vma */
static int file_start_context = 0; /* --file-start-context */
arelent ** dynrelbuf;
long dynrelcount;
disassembler_ftype disassemble_fn;
+#ifdef DISASSEMBLER_NEEDS_RELOCS
+ arelent * reloc;
+#endif
};
/* Architecture to disassemble for, or default if NULL. */
--prefix-addresses Print complete address alongside disassembly\n\
--[no-]show-raw-insn Display hex alongside symbolic disassembly\n\
--adjust-vma=OFFSET Add OFFSET to all displayed section addresses\n\
+ --special-syms Include special symbols in symbol dumps\n\
\n"));
list_supported_targets (program_name, stream);
list_supported_architectures (program_name, stream);
{"section-headers", no_argument, NULL, 'h'},
{"show-raw-insn", no_argument, &show_raw_insn, 1},
{"source", no_argument, NULL, 'S'},
+ {"special-syms", no_argument, &dump_special_syms, 1},
{"include", required_argument, NULL, 'I'},
{"stabs", no_argument, NULL, 'G'},
{"start-address", required_argument, NULL, OPTION_START_ADDRESS},
}
\f
static void
-dump_section_header (bfd *abfd ATTRIBUTE_UNUSED, asection *section,
+dump_section_header (bfd *abfd, asection *section,
void *ignored ATTRIBUTE_UNUSED)
{
char *comma = "";
unsigned int opb = bfd_octets_per_byte (abfd);
+ /* Ignore linker created section. See elfNN_ia64_object_p in
+ bfd/elfxx-ia64.c. */
+ if (section->flags & SEC_LINKER_CREATED)
+ return;
+
printf ("%3d %-13s %08lx ", section->index,
bfd_get_section_name (abfd, section),
(unsigned long) bfd_section_size (abfd, section) / opb);
PF (SEC_NEVER_LOAD, "NEVER_LOAD");
PF (SEC_EXCLUDE, "EXCLUDE");
PF (SEC_SORT_ENTRIES, "SORT_ENTRIES");
- PF (SEC_BLOCK, "BLOCK");
- PF (SEC_CLINK, "CLINK");
+ if (bfd_get_arch (abfd) == bfd_arch_tic54x)
+ {
+ PF (SEC_TIC54X_BLOCK, "BLOCK");
+ PF (SEC_TIC54X_CLINK, "CLINK");
+ }
PF (SEC_SMALL_DATA, "SMALL_DATA");
- PF (SEC_SHARED, "SHARED");
- PF (SEC_ARCH_BIT_0, "ARCH_BIT_0");
+ if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+ PF (SEC_COFF_SHARED, "SHARED");
PF (SEC_THREAD_LOCAL, "THREAD_LOCAL");
+ PF (SEC_GROUP, "GROUP");
if ((section->flags & SEC_LINK_ONCE) != 0)
{
const char *ls;
+ struct coff_comdat_info *comdat;
switch (section->flags & SEC_LINK_DUPLICATES)
{
}
printf ("%s%s", comma, ls);
- if (section->comdat != NULL)
- printf (" (COMDAT %s %ld)", section->comdat->name,
- section->comdat->symbol);
+ comdat = bfd_coff_get_comdat_section (abfd, section);
+ if (comdat != NULL)
+ printf (" (COMDAT %s %ld)", comdat->name, comdat->symbol);
comma = ", ";
}
if (sym->name == NULL || sym->name[0] == '\0')
continue;
- if (sym->flags & (BSF_DEBUGGING))
+ if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM))
continue;
if (bfd_is_und_section (sym->section)
|| bfd_is_com_section (sym->section))
bfd_boolean skip_zeroes)
{
struct objdump_disasm_info *aux;
- asymbol *sym;
+ asymbol *sym = NULL; /* Initialize to avoid compiler warning. */
+#ifdef DISASSEMBLER_NEEDS_RELOCS
+ bfd_boolean skip_find = FALSE;
+#endif
if (sorted_symcount < 1)
{
}
aux = (struct objdump_disasm_info *) info->application_data;
- sym = find_symbol_for_address (vma, info, NULL);
+
+#ifdef DISASSEMBLER_NEEDS_RELOCS
+ if (aux->reloc != NULL
+ && aux->reloc->sym_ptr_ptr != NULL
+ && * aux->reloc->sym_ptr_ptr != NULL)
+ {
+ sym = * aux->reloc->sym_ptr_ptr;
+
+ /* Adjust the vma to the reloc. */
+ vma += bfd_asymbol_value (sym);
+
+ if (bfd_is_und_section (bfd_get_section (sym)))
+ skip_find = TRUE;
+ }
+
+ if (!skip_find)
+#endif
+ sym = find_symbol_for_address (vma, info, NULL);
+
objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, info,
skip_zeroes);
}
/* The number of zeroes we want to see before we start skipping them.
The number is arbitrarily chosen. */
-#ifndef SKIP_ZEROES
-#define SKIP_ZEROES (8)
-#endif
+#define DEFAULT_SKIP_ZEROES 8
/* The number of zeroes to skip at the end of a section. If the
number of zeroes at the end is between SKIP_ZEROES_AT_END and
attempt to avoid disassembling zeroes inserted by section
alignment. */
-#ifndef SKIP_ZEROES_AT_END
-#define SKIP_ZEROES_AT_END (3)
-#endif
+#define DEFAULT_SKIP_ZEROES_AT_END 3
/* Disassemble some data in memory between given values. */
bfd_boolean done_dot;
int skip_addr_chars;
bfd_vma addr_offset;
- int opb = info->octets_per_byte;
+ unsigned int opb = info->octets_per_byte;
+ unsigned int skip_zeroes = info->skip_zeroes;
+ unsigned int skip_zeroes_at_end = info->skip_zeroes_at_end;
+ int octets = opb;
SFILE sfile;
aux = (struct objdump_disasm_info *) info->application_data;
while (addr_offset < stop_offset)
{
bfd_vma z;
- int octets = 0;
bfd_boolean need_nl = FALSE;
+#ifdef DISASSEMBLER_NEEDS_RELOCS
+ int previous_octets;
+
+ /* Remember the length of the previous instruction. */
+ previous_octets = octets;
+#endif
+ octets = 0;
/* If we see more than SKIP_ZEROES octets of zeroes, we just
print `...'. */
if (! disassemble_zeroes
&& (info->insn_info_valid == 0
|| info->branch_delay_insns == 0)
- && (z - addr_offset * opb >= SKIP_ZEROES
+ && (z - addr_offset * opb >= skip_zeroes
|| (z == stop_offset * opb &&
- z - addr_offset * opb < SKIP_ZEROES_AT_END)))
+ z - addr_offset * opb < skip_zeroes_at_end)))
{
printf ("\t...\n");
{
sfile.pos = 0;
info->fprintf_func = (fprintf_ftype) objdump_sprintf;
- info->stream = (FILE *) &sfile;
+ info->stream = &sfile;
info->bytes_per_line = 0;
info->bytes_per_chunk = 0;
+ info->flags = 0;
#ifdef DISASSEMBLER_NEEDS_RELOCS
- /* FIXME: This is wrong. It tests the number of octets
- in the last instruction, not the current one. */
- if (*relppp < relppend
- && (**relppp)->address >= rel_offset + addr_offset
- && ((**relppp)->address
- < rel_offset + addr_offset + octets / opb))
- info->flags = INSN_HAS_RELOC;
- else
+ if (*relppp < relppend)
+ {
+ bfd_signed_vma distance_to_rel;
+
+ distance_to_rel = (**relppp)->address
+ - (rel_offset + addr_offset);
+
+ /* Check to see if the current reloc is associated with
+ the instruction that we are about to disassemble. */
+ if (distance_to_rel == 0
+ /* FIXME: This is wrong. We are trying to catch
+ relocs that are addressed part way through the
+ current instruction, as might happen with a packed
+ VLIW instruction. Unfortunately we do not know the
+ length of the current instruction since we have not
+ disassembled it yet. Instead we take a guess based
+ upon the length of the previous instruction. The
+ proper solution is to have a new target-specific
+ disassembler function which just returns the length
+ of an instruction at a given address without trying
+ to display its disassembly. */
+ || (distance_to_rel > 0
+ && distance_to_rel < (bfd_signed_vma) (previous_octets/ opb)))
+ {
+ info->flags = INSN_HAS_RELOC;
+ aux->reloc = **relppp;
+ }
+ else
+ aux->reloc = NULL;
+ }
#endif
- info->flags = 0;
-
octets = (*disassemble_fn) (section->vma + addr_offset, info);
info->fprintf_func = (fprintf_ftype) fprintf;
info->stream = stdout;
for (j = addr_offset * opb; j < addr_offset * opb + pb; j += bpc)
{
int k;
+
if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE)
{
for (k = bpc - 1; k >= 0; k--)
code are not normally disassembled. */
if (! disassemble_all
&& only == NULL
- && (section->flags & SEC_CODE) == 0)
+ && ((section->flags & (SEC_CODE | SEC_HAS_CONTENTS))
+ != (SEC_CODE | SEC_HAS_CONTENTS)))
return;
if (! process_section_p (section))
return;
- datasize = bfd_get_section_size_before_reloc (section);
+ datasize = bfd_get_section_size (section);
if (datasize == 0)
return;
aux.require_sec = FALSE;
aux.dynrelbuf = NULL;
aux.dynrelcount = 0;
+#ifdef DISASSEMBLER_NEEDS_RELOCS
+ aux.reloc = NULL;
+#endif
disasm_info.print_address_func = objdump_print_address;
disasm_info.symbol_at_address_func = objdump_symbol_at_address;
disasm_info.mach = bfd_get_mach (abfd);
disasm_info.disassembler_options = disassembler_options;
disasm_info.octets_per_byte = bfd_octets_per_byte (abfd);
+ disasm_info.skip_zeroes = DEFAULT_SKIP_ZEROES;
+ disasm_info.skip_zeroes_at_end = DEFAULT_SKIP_ZEROES_AT_END;
if (bfd_big_endian (abfd))
disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_BIG;
if (strtab)
{
- stabs = read_section_stabs (abfd, section->name, &stab_size);
+ stabs = (bfd_byte *) read_section_stabs (abfd, section->name,
+ &stab_size);
if (stabs)
print_section_stabs (abfd, section->name, &sought->string_offset);
}
bfd *cur_bfd;
if (*current == NULL)
- printf (_("no information for the %ld'th symbol"), count);
+ printf (_("no information for symbol number %ld\n"), count);
else if ((cur_bfd = bfd_asymbol_bfd (*current)) == NULL)
- printf (_("could not determine the type of the %ld'th symbol"),
+ printf (_("could not determine the type of symbol number %ld\n"),
count);
- else
+ else if (process_section_p ((* current)->section)
+ && (dump_special_syms
+ || !bfd_is_target_special_symbol (cur_bfd, *current)))
{
const char *name = (*current)->name;
else
bfd_print_symbol (cur_bfd, stdout, *current,
bfd_print_symbol_all);
+ printf ("\n");
}
- printf ("\n");
current++;
}
printf ("\n\n");
if (dump_dynamic_symtab || dump_dynamic_reloc_info
|| (disassemble && bfd_get_dynamic_symtab_upper_bound (abfd) > 0))
dynsyms = slurp_dynamic_symtab (abfd);
- if (disassemble && dynsymcount > 0)
+ if (disassemble)
{
- synthcount = bfd_get_synthetic_symtab (abfd, dynsyms, &synthsyms);
- if (synthcount < 0) synthcount = 0;
+ synthcount = bfd_get_synthetic_symtab (abfd, symcount, syms,
+ dynsymcount, dynsyms, &synthsyms);
+ if (synthcount < 0)
+ synthcount = 0;
}
if (dump_symtab)