/* objdump.c -- dump information about an object file.
- Copyright 1990-2013 Free Software Foundation, Inc.
+ Copyright (C) 1990-2016 Free Software Foundation, Inc.
This file is part of GNU Binutils.
relocations, debugging directives and more.
The flow of execution is as follows:
-
+
1. Command line arguments are checked for control switches and the
information to be displayed is selected.
-
+
2. Any remaining arguments are assumed to be object files, and they are
processed in order by display_bfd(). If the file is an archive each
of its elements is processed in turn.
-
+
3. The file's target architecture and binary file format are determined
by bfd_check_format(). If they are recognised, then dump_bfd() is
called.
#include "sysdep.h"
#include "bfd.h"
#include "elf-bfd.h"
+#include "coff-bfd.h"
#include "progress.h"
#include "bucomm.h"
#include "elfcomm.h"
}
PF (SEC_SMALL_DATA, "SMALL_DATA");
if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
- PF (SEC_COFF_SHARED, "SHARED");
+ {
+ PF (SEC_COFF_SHARED, "SHARED");
+ PF (SEC_COFF_NOREAD, "NOREAD");
+ }
+ else if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+ {
+ /* Note - sections can have both the READONLY and NOREAD attributes
+ set. In this case the NOREAD takes precedence, but we report both
+ since the user may need to know that both bits are set. */
+ PF (SEC_ELF_NOREAD, "NOREAD");
+ }
PF (SEC_THREAD_LOCAL, "THREAD_LOCAL");
PF (SEC_GROUP, "GROUP");
+ if (bfd_get_arch (abfd) == bfd_arch_mep)
+ {
+ PF (SEC_MEP_VLIW, "VLIW");
+ }
if ((section->flags & SEC_LINK_ONCE) != 0)
{
storage = bfd_get_symtab_upper_bound (abfd);
if (storage < 0)
- bfd_fatal (bfd_get_filename (abfd));
+ {
+ non_fatal (_("failed to read symbol table from: %s"), bfd_get_filename (abfd));
+ bfd_fatal (_("error message was"));
+ }
if (storage)
sy = (asymbol **) xmalloc (storage);
asymbol *sym)
{
char *alloc;
- const char *name;
+ const char *name, *version_string = NULL;
+ bfd_boolean hidden = FALSE;
alloc = NULL;
name = bfd_asymbol_name (sym);
name = alloc;
}
+ if ((sym->flags & BSF_SYNTHETIC) == 0)
+ version_string = bfd_get_symbol_version_string (abfd, sym, &hidden);
+
+ if (bfd_is_und_section (bfd_get_section (sym)))
+ hidden = TRUE;
+
if (inf != NULL)
- (*inf->fprintf_func) (inf->stream, "%s", name);
+ {
+ (*inf->fprintf_func) (inf->stream, "%s", name);
+ if (version_string && *version_string != '\0')
+ (*inf->fprintf_func) (inf->stream, hidden ? "@%s" : "@@%s",
+ version_string);
+ }
else
- printf ("%s", name);
+ {
+ printf ("%s", name);
+ if (version_string && *version_string != '\0')
+ printf (hidden ? "@%s" : "@@%s", version_string);
+ }
if (alloc != NULL)
free (alloc);
sections have overlapping memory ranges, but in that case there's
no way to tell what's desired without looking at the relocation
table.
-
+
Also give the target a chance to reject symbols. */
want_section = (aux->require_sec
|| ((abfd->flags & HAS_RELOC) != 0
struct print_file_list *next;
const char *filename;
const char *modname;
- const char *map;
+ const char *map;
size_t mapsize;
- const char **linemap;
+ const char **linemap;
unsigned maxline;
unsigned last_line;
+ unsigned max_printed;
int first;
};
/* Precompute array of lines for a mapped file. */
-static const char **
-index_file (const char *map, size_t size, unsigned int *maxline)
+static const char **
+index_file (const char *map, size_t size, unsigned int *maxline)
{
const char *p, *lstart, *end;
int chars_per_line = 45; /* First iteration will use 40. */
unsigned int lineno;
- const char **linemap = NULL;
+ const char **linemap = NULL;
unsigned long line_map_size = 0;
-
+
lineno = 0;
lstart = map;
end = map + size;
- for (p = map; p < end; p++)
- {
- if (*p == '\n')
- {
- if (p + 1 < end && p[1] == '\r')
- p++;
- }
- else if (*p == '\r')
- {
+ for (p = map; p < end; p++)
+ {
+ if (*p == '\n')
+ {
+ if (p + 1 < end && p[1] == '\r')
+ p++;
+ }
+ else if (*p == '\r')
+ {
if (p + 1 < end && p[1] == '\n')
p++;
}
else
continue;
-
+
/* End of line found. */
- if (linemap == NULL || line_map_size < lineno + 1)
- {
+ if (linemap == NULL || line_map_size < lineno + 1)
+ {
unsigned long newsize;
chars_per_line -= line_map_decrease;
linemap = (const char **) xrealloc (linemap, newsize);
}
- linemap[lineno++] = lstart;
- lstart = p + 1;
+ linemap[lineno++] = lstart;
+ lstart = p + 1;
}
-
- *maxline = lineno;
+
+ *maxline = lineno;
return linemap;
}
free (p);
return NULL;
}
-
+
p->linemap = index_file (p->map, p->mapsize, &p->maxline);
p->last_line = 0;
+ p->max_printed = 0;
p->filename = origname;
p->modname = modname;
p->next = print_files;
/* Print a source file line. */
-static void
+static void
print_line (struct print_file_list *p, unsigned int linenum)
{
const char *l;
size_t len;
-
- --linenum;
+
+ --linenum;
if (linenum >= p->maxline)
return;
l = p->linemap [linenum];
{
if (p->map == NULL)
return;
- while (start <= end)
+ while (start <= end)
{
print_line (p, start);
start++;
unsigned int linenumber;
unsigned int discriminator;
bfd_boolean reloc;
+ char *path = NULL;
if (! with_line_numbers && ! with_source_code)
return;
{
char *path_up;
const char *fname = filename;
- char *path = (char *) alloca (prefix_length + PATH_MAX + 1);
+
+ path = xmalloc (prefix_length + PATH_MAX + 1);
if (prefix_length)
memcpy (path, prefix, prefix_length);
path_up = path + prefix_length;
/* Build relocated filename, stripping off leading directories
- from the initial filename if requested. */
+ from the initial filename if requested. */
if (prefix_strip > 0)
{
int level = 0;
const char *s;
- /* Skip selected directory levels. */
+ /* Skip selected directory levels. */
for (s = fname + 1; *s != '\0' && level < prefix_strip; s++)
if (IS_DIR_SEPARATOR(*s))
{
}
}
- /* Update complete filename. */
+ /* Update complete filename. */
strncpy (path_up, fname, PATH_MAX);
path_up[PATH_MAX] = '\0';
&& (prev_functionname == NULL
|| strcmp (functionname, prev_functionname) != 0))
printf ("%s():\n", functionname);
- if (linenumber > 0 && (linenumber != prev_line ||
+ if (linenumber > 0 && (linenumber != prev_line ||
(discriminator != prev_discriminator)))
- {
+ {
if (discriminator > 0)
printf ("%s:%u (discriminator %u)\n", filename == NULL ? "???" : filename,
linenumber, discriminator);
if (p != NULL && linenumber != p->last_line)
{
- if (file_start_context && p->first)
+ if (file_start_context && p->first)
l = 1;
- else
+ else
{
l = linenumber - SHOW_PRECEDING_CONTEXT_LINES;
- if (l >= linenumber)
+ if (l >= linenumber)
l = 1;
- if (p->last_line >= l && p->last_line <= linenumber)
- l = p->last_line + 1;
+ if (p->max_printed >= l)
+ {
+ if (p->max_printed < linenumber)
+ l = p->max_printed + 1;
+ else
+ l = linenumber;
+ }
}
dump_lines (p, l, linenumber);
+ if (p->max_printed < linenumber)
+ p->max_printed = linenumber;
p->last_line = linenumber;
p->first = 0;
}
if (discriminator != prev_discriminator)
prev_discriminator = discriminator;
+
+ if (path)
+ free (path);
}
/* Pseudo FILE object for strings. */
while (1)
{
size_t space = f->alloc - f->pos;
-
+
va_start (args, format);
n = vsnprintf (f->buffer + f->pos, space, format, args);
va_end (args);
if (space > n)
break;
-
+
f->alloc = (f->alloc + n) * 2;
f->buffer = (char *) xrealloc (f->buffer, f->alloc);
}
f->pos += n;
-
+
return n;
}
sfile.alloc = 120;
sfile.buffer = (char *) xmalloc (sfile.alloc);
sfile.pos = 0;
-
+
if (insn_width)
octets_per_line = insn_width;
else if (insns)
}
}
+ if (! disassemble_all
+ && (section->flags & (SEC_CODE | SEC_HAS_CONTENTS))
+ == (SEC_CODE | SEC_HAS_CONTENTS))
+ /* Set a stop_vma so that the disassembler will not read
+ beyond the next symbol. We assume that symbols appear on
+ the boundaries between instructions. We only do this when
+ disassembling code of course, and when -D is in effect. */
+ inf->stop_vma = section->vma + stop_offset;
+
octets = (*disassemble_fn) (section->vma + addr_offset, inf);
+
+ inf->stop_vma = 0;
inf->fprintf_func = (fprintf_ftype) fprintf;
inf->stream = stdout;
if (insn_width == 0 && inf->bytes_per_line != 0)
arelent ** rel_pp = NULL;
arelent ** rel_ppstart = NULL;
arelent ** rel_ppend;
- unsigned long stop_offset;
+ bfd_vma stop_offset;
asymbol * sym = NULL;
long place = 0;
long rel_count;
{
bfd_vma addr;
asymbol *nextsym;
- unsigned long nextstop_offset;
+ bfd_vma nextstop_offset;
bfd_boolean insns;
addr = section->vma + addr_offset;
((SYM)->section == section \
&& (bfd_asymbol_value (SYM) > bfd_asymbol_value (sym)) \
&& pinfo->symbol_is_valid (SYM, pinfo))
-
+
/* Search forward for the next appropriate symbol in
SECTION. Note that all the symbols are sorted
together into one big array, and that some sections
disassemble_bytes (pinfo, paux->disassemble_fn, insns, data,
addr_offset, nextstop_offset,
rel_offset, &rel_pp, rel_ppend);
-
+
addr_offset = nextstop_offset;
sym = nextsym;
}
if (dump_dynamic_reloc_info)
{
long relsize = bfd_get_dynamic_reloc_upper_bound (abfd);
-
+
if (relsize < 0)
bfd_fatal (bfd_get_filename (abfd));
if (section->start != NULL)
return 1;
- section->address = 0;
+ section->reloc_info = NULL;
+ section->num_relocs = 0;
+ section->address = bfd_get_section_vma (abfd, sec);
section->size = bfd_get_section_size (sec);
section->start = NULL;
+ section->user_data = sec;
ret = bfd_get_full_section_contents (abfd, sec, §ion->start);
if (! ret)
section->name);
return 0;
}
+
+ long reloc_size;
+
+ reloc_size = bfd_get_reloc_upper_bound (abfd, sec);
+ if (reloc_size > 0)
+ {
+ unsigned long reloc_count;
+ arelent **relocs;
+
+ relocs = (arelent **) xmalloc (reloc_size);
+
+ reloc_count = bfd_canonicalize_reloc (abfd, sec, relocs, NULL);
+ if (reloc_count == 0)
+ free (relocs);
+ else
+ {
+ section->reloc_info = relocs;
+ section->num_relocs = reloc_count;
+ }
+ }
}
return 1;
}
+bfd_boolean
+reloc_at (struct dwarf_section * dsec, dwarf_vma offset)
+{
+ arelent ** relocs;
+ arelent * rp;
+
+ if (dsec == NULL || dsec->reloc_info == NULL)
+ return FALSE;
+
+ relocs = (arelent **) dsec->reloc_info;
+
+ for (; (rp = * relocs) != NULL; ++ relocs)
+ if (rp->address == offset)
+ return TRUE;
+
+ return FALSE;
+}
+
int
load_debug_section (enum dwarf_section_display_enum debug, void *file)
{
if (section->start == NULL)
return;
+ /* PR 17512: file: 0f67f69d. */
+ if (section->user_data != NULL)
+ {
+ asection * sec = (asection *) section->user_data;
+
+ /* If we are freeing contents that are also pointed to by the BFD
+ library's section structure then make sure to update those pointers
+ too. Otherwise, the next time we try to load data for this section
+ we can end up using a stale pointer. */
+ if (section->start == sec->contents)
+ {
+ sec->contents = NULL;
+ sec->flags &= ~ SEC_IN_MEMORY;
+ sec->compress_status = COMPRESS_SECTION_NONE;
+ }
+ }
+
free ((char *) section->start);
section->start = NULL;
section->address = 0;
section, abfd))
{
debug_displays [i].display (sec, abfd);
-
+
if (i != info && i != abbrev)
free_debug_section ((enum dwarf_section_display_enum) i);
}
else if (bfd_little_endian (abfd))
byte_get = byte_get_little_endian;
else
- abort ();
+ /* PR 17512: file: objdump-s-endless-loop.tekhex. */
+ {
+ warn (_("File %s does not contain any dwarf debug information\n"),
+ bfd_get_filename (abfd));
+ return;
+ }
switch (bfd_get_arch (abfd))
{
{
case bfd_mach_x86_64:
case bfd_mach_x86_64_intel_syntax:
+ case bfd_mach_x86_64_nacl:
case bfd_mach_x64_32:
case bfd_mach_x64_32_intel_syntax:
+ case bfd_mach_x64_32_nacl:
init_dwarf_regnames_x86_64 ();
break;
}
break;
+ case bfd_arch_iamcu:
+ init_dwarf_regnames_iamcu ();
+ break;
+
+ case bfd_arch_aarch64:
+ init_dwarf_regnames_aarch64();
+ break;
+
+ case bfd_arch_s390:
+ init_dwarf_regnames_s390 ();
+ break;
+
default:
break;
}
We start the index at -1 because there is a dummy symbol on
the front of stabs-in-{coff,elf} sections that supplies sizes. */
- for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++)
+ for (i = -1; stabp <= stabs_end - STABSIZE; stabp += STABSIZE, i++)
{
const char *name;
unsigned long strx;
}
else
{
+ bfd_size_type amt = strx + file_string_table_offset;
+
/* Using the (possibly updated) string table offset, print the
string (if any) associated with this symbol. */
- if ((strx + file_string_table_offset) < stabstr_size)
- printf (" %s", &strtab[strx + file_string_table_offset]);
+ if (amt < stabstr_size)
+ /* PR 17512: file: 079-79389-0.001:0.1. */
+ printf (" %.*s", (int)(stabstr_size - amt), strtab + amt);
else
printf (" *");
}
if (strtab == NULL)
strtab = read_section_stabs (abfd, sought->string_section_name,
&stabstr_size);
-
+
if (strtab)
{
stabs = (bfd_byte *) read_section_stabs (abfd, section->name,
PF (WP_TEXT, "WP_TEXT");
PF (D_PAGED, "D_PAGED");
PF (BFD_IS_RELAXABLE, "BFD_IS_RELAXABLE");
- PF (HAS_LOAD_PAGE, "HAS_LOAD_PAGE");
printf (_("\nstart address 0x"));
bfd_printf_vma (abfd, abfd->start_address);
printf ("\n");
{
bfd_byte *data = 0;
bfd_size_type datasize;
- bfd_size_type addr_offset;
- bfd_size_type start_offset;
- bfd_size_type stop_offset;
+ bfd_vma addr_offset;
+ bfd_vma start_offset;
+ bfd_vma stop_offset;
unsigned int opb = bfd_octets_per_byte (abfd);
/* Bytes per line. */
const int onaline = 16;
if (! process_section_p (section))
return;
-
+
if ((datasize = bfd_section_size (abfd, section)) == 0)
return;
if (start_offset >= stop_offset)
return;
-
+
printf (_("Contents of section %s:"), section->name);
if (display_file_offsets)
printf (_(" (Starting at file offset: 0x%lx)"),
if (!bfd_get_full_section_contents (abfd, section, &data))
{
- non_fatal (_("Reading section failed"));
+ non_fatal (_("Reading section %s failed because: %s"),
+ section->name, bfd_errmsg (bfd_get_error ()));
return;
}
relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
if (relcount < 0)
- bfd_fatal (bfd_get_filename (abfd));
+ {
+ printf ("\n");
+ non_fatal (_("failed to read relocs in: %s"), bfd_get_filename (abfd));
+ bfd_fatal (_("error message was"));
+ }
else if (relcount == 0)
printf (" (none)\n\n");
else
info in the file, try DWARF instead. */
else if (! dump_dwarf_section_info)
{
- dwarf_select_sections_all ();
+ dwarf_select_sections_all ();
dump_dwarf (abfd);
}
}
if (level == 0)
printf (_("In archive %s:\n"), bfd_get_filename (file));
+ else if (level > 100)
+ {
+ /* Prevent corrupted files from spinning us into an
+ infinite loop. 100 is an arbitrary heuristic. */
+ fatal (_("Archive nesting is too deep"));
+ return;
+ }
else
printf (_("In nested archive %s:\n"), bfd_get_filename (file));
display_any_bfd (arfile, level + 1);
if (last_arfile != NULL)
- bfd_close (last_arfile);
+ {
+ bfd_close (last_arfile);
+ /* PR 17512: file: ac585d01. */
+ if (arfile == last_arfile)
+ {
+ last_arfile = NULL;
+ break;
+ }
+ }
last_arfile = arfile;
}
program_name = *argv;
xmalloc_set_program_name (program_name);
+ bfd_set_error_program_name (program_name);
START_PROGRESS (program_name, 0);