/* objdump.c -- dump information about an object file.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GNU Binutils.
#include "elf-bfd.h"
#include "progress.h"
#include "bucomm.h"
+#include "elfcomm.h"
#include "dwarf.h"
#include "getopt.h"
#include "safe-ctype.h"
static bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */
static int dump_debugging; /* --debugging */
static int dump_debugging_tags; /* --debugging-tags */
+static int suppress_bfd_header;
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 */
static int prefix_strip; /* --prefix-strip */
static size_t prefix_length;
-/* Pointer to an array of section names provided by
- one or more "-j secname" command line options. */
-static char **only;
-/* The total number of slots in the only[] array. */
-static size_t only_size = 0;
-/* The number of occupied slots in the only[] array. */
-static size_t only_used = 0;
+/* A structure to record the sections mentioned in -j switches. */
+struct only
+{
+ const char * name; /* The name of the section. */
+ bfd_boolean seen; /* A flag to indicate that the section has been found in one or more input files. */
+ struct only * next; /* Pointer to the next structure in the list. */
+};
+/* Pointer to an array of 'only' structures.
+ This pointer is NULL if the -j switch has not been used. */
+static struct only * only_list = NULL;
/* Variables for handling include file path table. */
static const char **include_paths;
-G, --stabs Display (in raw form) any STABS info in the file\n\
-W[lLiaprmfFsoRt] or\n\
--dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,\n\
- =frames-interp,=str,=loc,=Ranges,=pubtypes]\n\
+ =frames-interp,=str,=loc,=Ranges,=pubtypes,\n\
+ =gdb_index,=trace_info,=trace_abbrev,=trace_aranges]\n\
Display DWARF info in the file\n\
-t, --syms Display the contents of the symbol table(s)\n\
-T, --dynamic-syms Display the contents of the dynamic symbol table\n\
--stop-address=ADDR Only process data whose address is <= ADDR\n\
--prefix-addresses Print complete address alongside disassembly\n\
--[no-]show-raw-insn Display hex alongside symbolic disassembly\n\
- --insn-width=WIDTH Display WIDTH bytes on a signle line for -d\n\
+ --insn-width=WIDTH Display WIDTH bytes on a single line for -d\n\
--adjust-vma=OFFSET Add OFFSET to all displayed section addresses\n\
--special-syms Include special symbols in symbol dumps\n\
--prefix=PREFIX Add PREFIX to absolute paths for -S\n\
- --prefix-strip=LEVEL Strip initial directory names for -S\n\
-\n"));
+ --prefix-strip=LEVEL Strip initial directory names for -S\n"));
+ fprintf (stream, _("\
+ --dwarf-depth=N Do not display DIEs at depth N or greater\n\
+ --dwarf-start=N Display DIEs starting with N, at the same depth\n\
+ or deeper\n\n"));
list_supported_targets (program_name, stream);
list_supported_architectures (program_name, stream);
OPTION_PREFIX,
OPTION_PREFIX_STRIP,
OPTION_INSN_WIDTH,
- OPTION_ADJUST_VMA
+ OPTION_ADJUST_VMA,
+ OPTION_DWARF_DEPTH,
+ OPTION_DWARF_START
};
static struct option long_options[]=
{"prefix", required_argument, NULL, OPTION_PREFIX},
{"prefix-strip", required_argument, NULL, OPTION_PREFIX_STRIP},
{"insn-width", required_argument, NULL, OPTION_INSN_WIDTH},
+ {"dwarf-depth", required_argument, 0, OPTION_DWARF_DEPTH},
+ {"dwarf-start", required_argument, 0, OPTION_DWARF_START},
{0, no_argument, 0, 0}
};
\f
static bfd_boolean
process_section_p (asection * section)
{
- size_t i;
+ struct only * only;
- if (only == NULL)
+ if (only_list == NULL)
return TRUE;
- for (i = 0; i < only_used; i++)
- if (strcmp (only [i], section->name) == 0)
- return TRUE;
+ for (only = only_list; only; only = only->next)
+ if (strcmp (only->name, section->name) == 0)
+ {
+ only->seen = TRUE;
+ return TRUE;
+ }
return FALSE;
}
+
+/* Add an entry to the 'only' list. */
+
+static void
+add_only (char * name)
+{
+ struct only * only;
+
+ /* First check to make sure that we do not
+ already have an entry for this name. */
+ for (only = only_list; only; only = only->next)
+ if (strcmp (only->name, name) == 0)
+ return;
+
+ only = xmalloc (sizeof * only);
+ only->name = name;
+ only->seen = FALSE;
+ only->next = only_list;
+ only_list = only;
+}
+
+/* Release the memory used by the 'only' list.
+ PR 11225: Issue a warning message for unseen sections.
+ Only do this if none of the sections were seen. This is mainly to support
+ tools like the GAS testsuite where an object file is dumped with a list of
+ generic section names known to be present in a range of different file
+ formats. */
+
+static void
+free_only_list (void)
+{
+ bfd_boolean at_least_one_seen = FALSE;
+ struct only * only;
+ struct only * next;
+
+ if (only_list == NULL)
+ return;
+
+ for (only = only_list; only; only = only->next)
+ if (only->seen)
+ {
+ at_least_one_seen = TRUE;
+ break;
+ }
+
+ for (only = only_list; only; only = next)
+ {
+ if (! at_least_one_seen)
+ {
+ non_fatal (_("section '%s' mentioned in a -j option, "
+ "but not found in any input file"),
+ only->name);
+ exit_status = 1;
+ }
+ next = only->next;
+ free (only);
+ }
+}
+
\f
static void
dump_section_header (bfd *abfd, asection *section,
if (wide_output)
printf (_(" Flags"));
- if (abfd->flags & HAS_LOAD_PAGE)
- printf (_(" Pg"));
printf ("\n");
bfd_map_over_sections (abfd, dump_section_header, NULL);
if (!(bfd_get_file_flags (abfd) & DYNAMIC))
{
non_fatal (_("%s: not a dynamic object"), bfd_get_filename (abfd));
+ exit_status = 1;
dynsymcount = 0;
return NULL;
}
const char *fname;
int i;
- if (filename == NULL)
- return NULL;
-
p = try_print_file_open (filename, filename);
if (p != NULL)
return p;
unsigned l;
for (pp = &print_files; *pp != NULL; pp = &(*pp)->next)
- if (strcmp ((*pp)->filename, filename) == 0)
+ if (filename_cmp ((*pp)->filename, filename) == 0)
break;
p = *pp;
struct objdump_disasm_info *aux;
asection *section;
int octets_per_line;
- bfd_boolean done_dot;
int skip_addr_chars;
bfd_vma addr_offset;
unsigned int opb = inf->octets_per_byte;
inf->insn_info_valid = 0;
- done_dot = FALSE;
addr_offset = start_offset;
while (addr_offset < stop_offset)
{
previous_octets = octets;
octets = 0;
+ /* Make sure we don't use relocs from previous instructions. */
+ aux->reloc = NULL;
+
/* If we see more than SKIP_ZEROES octets of zeroes, we just
print `...'. */
for (z = addr_offset * opb; z < stop_offset * opb; z++)
int bpc = 0;
int pb = 0;
- done_dot = FALSE;
-
if (with_line_numbers || with_source_code)
show_line (aux->abfd, section, addr_offset);
inf->flags |= INSN_HAS_RELOC;
aux->reloc = **relppp;
}
- else
- aux->reloc = NULL;
}
octets = (*disassemble_fn) (section->vma + addr_offset, inf);
inf->stream = stdout;
if (insn_width == 0 && inf->bytes_per_line != 0)
octets_per_line = inf->bytes_per_line;
- if (octets < 0)
+ if (octets < (int) opb)
{
if (sfile.pos)
printf ("%s\n", sfile.buffer);
+ if (octets >= 0)
+ {
+ non_fatal (_("disassemble_fn returned length %d"),
+ octets);
+ exit_status = 1;
+ }
break;
}
}
/* Sections that do not contain machine
code are not normally disassembled. */
if (! disassemble_all
- && only == NULL
+ && only_list == NULL
&& ((section->flags & (SEC_CODE | SEC_HAS_CONTENTS))
!= (SEC_CODE | SEC_HAS_CONTENTS)))
return;
const bfd_arch_info_type *inf = bfd_scan_arch (machine);
if (inf == NULL)
- fatal (_("Can't use supplied machine %s"), machine);
+ fatal (_("can't use supplied machine %s"), machine);
abfd->arch_info = inf;
}
aux.disassemble_fn = disassembler (abfd);
if (!aux.disassemble_fn)
{
- non_fatal (_("Can't disassemble for architecture %s\n"),
+ non_fatal (_("can't disassemble for architecture %s\n"),
bfd_printable_arch_mach (bfd_get_arch (abfd), 0));
exit_status = 1;
return;
struct dwarf_section *section = &debug_displays [debug].section;
bfd *abfd = (bfd *) file;
bfd_boolean ret;
- int section_is_compressed;
/* If it is already loaded, do nothing. */
if (section->start != NULL)
return 1;
- section_is_compressed = section->name == section->compressed_name;
-
section->address = 0;
section->size = bfd_get_section_size (sec);
- section->start = (unsigned char *) xmalloc (section->size);
-
- if (is_relocatable && debug_displays [debug].relocate)
- ret = bfd_simple_get_relocated_section_contents (abfd,
- sec,
- section->start,
- syms) != NULL;
- else
- ret = bfd_get_section_contents (abfd, sec, section->start, 0,
- section->size);
+ section->start = NULL;
+ ret = bfd_get_full_section_contents (abfd, sec, §ion->start);
if (! ret)
{
return 0;
}
- if (section_is_compressed)
+ if (is_relocatable && debug_displays [debug].relocate)
{
- bfd_size_type size = section->size;
- if (! bfd_uncompress_section_contents (§ion->start, &size))
+ /* We want to relocate the data we've already read (and
+ decompressed), so we store a pointer to the data in
+ the bfd_section, and tell it that the contents are
+ already in memory. */
+ sec->contents = section->start;
+ sec->flags |= SEC_IN_MEMORY;
+ sec->size = section->size;
+
+ ret = bfd_simple_get_relocated_section_contents (abfd,
+ sec,
+ section->start,
+ syms) != NULL;
+
+ if (! ret)
{
free_debug_section (debug);
- printf (_("\nCan't uncompress section '%s'.\n"), section->name);
+ printf (_("\nCan't get contents for section '%s'.\n"),
+ section->name);
return 0;
}
- section->size = size;
}
return 1;
{
is_relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
- /* FIXME: bfd_get_arch_size may return -1. We assume that 64bit
- targets will return 64. */
- eh_addr_size = bfd_get_arch_size (abfd) == 64 ? 8 : 4;
+ eh_addr_size = bfd_arch_bits_per_address (abfd) / 8;
if (bfd_big_endian (abfd))
byte_get = byte_get_big_endian;
else
abort ();
- if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+ switch (bfd_get_arch (abfd))
{
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- init_dwarf_regnames (bed->elf_machine_code);
+ case bfd_arch_i386:
+ switch (bfd_get_mach (abfd))
+ {
+ case bfd_mach_x86_64:
+ case bfd_mach_x86_64_intel_syntax:
+ init_dwarf_regnames_x86_64 ();
+ break;
+
+ default:
+ init_dwarf_regnames_i386 ();
+ break;
+ }
+ break;
+
+ default:
+ break;
}
bfd_map_over_sections (abfd, dump_dwarf_section, NULL);
if (! bfd_get_section_contents (abfd, stabsect, contents, 0, size))
{
- non_fatal (_("Reading %s section of %s failed: %s"),
+ non_fatal (_("reading %s section of %s failed: %s"),
sect_name, bfd_get_filename (abfd),
bfd_errmsg (bfd_get_error ()));
- free (contents);
exit_status = 1;
+ free (contents);
return NULL;
}
printf (_("architecture: %s, "),
bfd_printable_arch_mach (bfd_get_arch (abfd),
bfd_get_mach (abfd)));
- printf (_("flags 0x%08x:\n"), abfd->flags);
+ printf (_("flags 0x%08x:\n"), abfd->flags & ~BFD_FLAGS_FOR_BFD_USE_MASK);
#define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";}
PF (HAS_RELOC, "HAS_RELOC");
(unsigned long) (section->filepos + start_offset));
printf ("\n");
- data = (bfd_byte *) xmalloc (datasize);
-
- bfd_get_section_contents (abfd, section, data, 0, datasize);
+ if (!bfd_get_full_section_contents (abfd, section, &data))
+ {
+ non_fatal (_("Reading section failed"));
+ return;
+ }
width = 4;
unsigned int linenumber;
const char *sym_name;
const char *section_name;
+ bfd_vma addend2 = 0;
if (start_address != (bfd_vma) -1
&& q->address < start_address)
&& (linenumber != last_line
|| (filename != NULL
&& last_filename != NULL
- && strcmp (filename, last_filename) != 0)))
+ && filename_cmp (filename, last_filename) != 0)))
{
printf ("%s:%u\n", filename == NULL ? "???" : filename, linenumber);
last_line = linenumber;
if (q->howto == NULL)
printf (" *unknown* ");
else if (q->howto->name)
- printf (" %-16s ", q->howto->name);
+ {
+ const char *name = q->howto->name;
+
+ /* R_SPARC_OLO10 relocations contain two addends.
+ But because 'arelent' lacks enough storage to
+ store them both, the 64-bit ELF Sparc backend
+ records this as two relocations. One R_SPARC_LO10
+ and one R_SPARC_13, both pointing to the same
+ address. This is merely so that we have some
+ place to store both addend fields.
+
+ Undo this transformation, otherwise the output
+ will be confusing. */
+ if (abfd->xvec->flavour == bfd_target_elf_flavour
+ && elf_tdata(abfd)->elf_header->e_machine == EM_SPARCV9
+ && relcount > 1
+ && !strcmp (q->howto->name, "R_SPARC_LO10"))
+ {
+ arelent *q2 = *(p + 1);
+ if (q2 != NULL
+ && q2->howto
+ && q->address == q2->address
+ && !strcmp (q2->howto->name, "R_SPARC_13"))
+ {
+ name = "R_SPARC_OLO10";
+ addend2 = q2->addend;
+ p++;
+ }
+ }
+ printf (" %-16s ", name);
+ }
else
printf (" %-16d ", q->howto->type);
printf ("+0x");
bfd_printf_vma (abfd, q->addend);
}
+ if (addend2)
+ {
+ printf ("+0x");
+ bfd_printf_vma (abfd, addend2);
+ }
printf ("\n");
}
+
+ if (last_filename != NULL)
+ free (last_filename);
+ if (last_functionname != NULL)
+ free (last_functionname);
}
static void
bfd_map_over_sections (abfd, adjust_addresses, &has_reloc);
}
- if (! dump_debugging_tags)
+ if (! dump_debugging_tags && ! suppress_bfd_header)
printf (_("\n%s: file format %s\n"), bfd_get_filename (abfd),
abfd->xvec->name);
if (dump_ar_hdrs)
dump_bfd_header (abfd);
if (dump_private_headers)
dump_bfd_private_header (abfd);
- if (! dump_debugging_tags)
+ if (! dump_debugging_tags && ! suppress_bfd_header)
putchar ('\n');
if (dump_section_headers)
dump_headers (abfd);
return;
}
+ /* Decompress sections unless dumping the section contents. */
+ if (!dump_section_contents)
+ file->flags |= BFD_DECOMPRESS;
+
/* If the file is an archive, process all of its elements. */
if (bfd_check_format (file, bfd_archive))
{
disassembler_options = optarg;
break;
case 'j':
- if (only_used == only_size)
- {
- only_size += 8;
- only = (char **) xrealloc (only, only_size * sizeof (char *));
- }
- only [only_used++] = optarg;
+ add_only (optarg);
break;
case 'F':
display_file_offsets = TRUE;
endian = BFD_ENDIAN_LITTLE;
else
{
- non_fatal (_("unrecognized -E option"));
+ nonfatal (_("unrecognized -E option"));
usage (stderr, 1);
}
break;
else
{
non_fatal (_("unrecognized --endian type `%s'"), optarg);
+ exit_status = 1;
usage (stderr, 1);
}
break;
else
dwarf_select_sections_all ();
break;
+ case OPTION_DWARF_DEPTH:
+ {
+ char *cp;
+ dwarf_cutoff_level = strtoul (optarg, & cp, 0);
+ }
+ break;
+ case OPTION_DWARF_START:
+ {
+ char *cp;
+ dwarf_start_die = strtoul (optarg, & cp, 0);
+ suppress_bfd_header = 1;
+ }
+ break;
case 'G':
dump_stab_section_info = TRUE;
seenflag = TRUE;
display_file (argv[optind++], target);
}
+ free_only_list ();
+
END_PROGRESS (program_name);
return exit_status;