/* objdump.c -- dump information about an object file.
- Copyright (C) 1990-2021 Free Software Foundation, Inc.
+ Copyright (C) 1990-2023 Free Software Foundation, Inc.
This file is part of GNU Binutils.
#include "bfd.h"
#include "elf-bfd.h"
#include "coff-bfd.h"
-#include "progress.h"
#include "bucomm.h"
#include "elfcomm.h"
+#include "demanguse.h"
#include "dwarf.h"
#include "ctf-api.h"
+#include "sframe-api.h"
#include "getopt.h"
#include "safe-ctype.h"
#include "dis-asm.h"
#include <sys/mman.h>
#endif
+#ifdef HAVE_LIBDEBUGINFOD
+#include <elfutils/debuginfod.h>
+#endif
+
/* Internal headers for the ELF .stab-dump code - sorry. */
#define BYTES_IN_WORD 32
#include "aout/aout64.h"
static int dump_ctf_section_info; /* --ctf */
static char *dump_ctf_section_name;
static char *dump_ctf_parent_name; /* --ctf-parent */
+static int dump_sframe_section_info; /* --sframe */
+static char *dump_sframe_section_name;
static int do_demangle; /* -C, --demangle */
static bool disassemble; /* -d */
static bool disassemble_all; /* -D */
static int disassemble_zeroes; /* --disassemble-zeroes */
static bool formats_info; /* -i */
-static int wide_output; /* -w */
+int wide_output; /* -w */
static int insn_width; /* --insn-width */
static bfd_vma start_address = (bfd_vma) -1; /* --start-address */
static bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */
static bool color_output = false; /* --visualize-jumps=color. */
static bool extended_color_output = false; /* --visualize-jumps=extended-color. */
static int process_links = false; /* --process-links. */
+static int show_all_symbols; /* --show-all-symbols. */
+
+static enum color_selection
+ {
+ on_if_terminal_output,
+ on, /* --disassembler-color=color. */
+ off, /* --disassembler-color=off. */
+ extended /* --disassembler-color=extended-color. */
+ } disassembler_color =
+#if DEFAULT_FOR_COLORED_DISASSEMBLY
+ on_if_terminal_output;
+#else
+ off;
+#endif
+static int dump_any_debugging;
static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
+/* This is reset to false each time we enter the disassembler, and set true
+ when the disassembler emits something in the dis_style_comment_start
+ style. Once this is true, all further output on that line is done in
+ the comment style. This only has an effect when disassembler coloring
+ is turned on. */
+static bool disassembler_in_comment = false;
+
/* A structure to record the sections mentioned in -j switches. */
struct only
{
/* The list of detected jumps inside a function. */
static struct jump_info *detected_jumps = NULL;
+
+typedef enum unicode_display_type
+{
+ unicode_default = 0,
+ unicode_locale,
+ unicode_escape,
+ unicode_hex,
+ unicode_highlight,
+ unicode_invalid
+} unicode_display_type;
+
+static unicode_display_type unicode_display = unicode_default;
\f
static void usage (FILE *, int) ATTRIBUTE_NORETURN;
static void
-WN,--dwarf=no-follow-links\n\
Do not follow links to separate debug info files\n\
(default)\n"));
+#endif
+#if HAVE_LIBDEBUGINFOD
+ fprintf (stream, _("\
+ -WD --dwarf=use-debuginfod\n\
+ When following links, also query debuginfod servers (default)\n"));
+ fprintf (stream, _("\
+ -WE --dwarf=do-not-use-debuginfod\n\
+ When following links, do not query debuginfod servers\n"));
#endif
fprintf (stream, _("\
-L, --process-links Display the contents of non-debug sections in\n\
separate debuginfo files. (Implies -WK)\n"));
#ifdef ENABLE_LIBCTF
fprintf (stream, _("\
- --ctf=SECTION Display CTF info from SECTION\n"));
+ --ctf[=SECTION] Display CTF info from SECTION, (default `.ctf')\n"));
#endif
+ fprintf (stream, _("\
+ --sframe[=SECTION] Display SFrame info from SECTION, (default '.sframe')\n"));
fprintf (stream, _("\
-t, --syms Display the contents of the symbol table(s)\n"));
fprintf (stream, _("\
fprintf (stream, _("\
-F, --file-offsets Include file offsets when displaying information\n"));
fprintf (stream, _("\
- -C, --demangle[=STYLE] Decode mangled/processed symbol names\n\
- The STYLE, if specified, can be `auto', `gnu',\n\
- `lucid', `arm', `hp', `edg', `gnu-v3', `java'\n\
- or `gnat'\n"));
+ -C, --demangle[=STYLE] Decode mangled/processed symbol names\n"));
+ display_demangler_styles (stream, _("\
+ STYLE can be "));
fprintf (stream, _("\
--recurse-limit Enable a limit on recursion whilst demangling\n\
(default)\n"));
fprintf (stream, _("\
-w, --wide Format output for more than 80 columns\n"));
fprintf (stream, _("\
+ -U[d|l|i|x|e|h] Controls the display of UTF-8 unicode characters\n\
+ --unicode=[default|locale|invalid|hex|escape|highlight]\n"));
+ fprintf (stream, _("\
-z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n"));
fprintf (stream, _("\
--start-address=ADDR Only process data whose address is >= ADDR\n"));
fprintf (stream, _("\
--adjust-vma=OFFSET Add OFFSET to all displayed section addresses\n"));
fprintf (stream, _("\
+ --show-all-symbols When disassembling, display all symbols at a given address\n"));
+ fprintf (stream, _("\
--special-syms Include special symbols in symbol dumps\n"));
fprintf (stream, _("\
--inlines Print all inlines for source line (with -l)\n"));
--visualize-jumps=extended-color\n\
Use extended 8-bit color codes\n"));
fprintf (stream, _("\
- --visualize-jumps=off Disable jump visualization\n\n"));
+ --visualize-jumps=off Disable jump visualization\n"));
+#if DEFAULT_FOR_COLORED_DISASSEMBLY
+ fprintf (stream, _("\
+ --disassembler-color=off Disable disassembler color output.\n"));
+ fprintf (stream, _("\
+ --disassembler-color=terminal Enable disassembler color output if displaying on a terminal. (default)\n"));
+#else
+ fprintf (stream, _("\
+ --disassembler-color=off Disable disassembler color output. (default)\n"));
+ fprintf (stream, _("\
+ --disassembler-color=terminal Enable disassembler color output if displaying on a terminal.\n"));
+#endif
+ fprintf (stream, _("\
+ --disassembler-color=on Enable disassembler color output.\n"));
+ fprintf (stream, _("\
+ --disassembler-color=extended Use 8-bit colors in disassembler output.\n\n"));
list_supported_targets (program_name, stream);
list_supported_architectures (program_name, stream);
OPTION_CTF,
OPTION_CTF_PARENT,
#endif
- OPTION_VISUALIZE_JUMPS
+ OPTION_SFRAME,
+ OPTION_VISUALIZE_JUMPS,
+ OPTION_DISASSEMBLER_COLOR
};
static struct option long_options[]=
{
{"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA},
{"all-headers", no_argument, NULL, 'x'},
- {"private-headers", no_argument, NULL, 'p'},
- {"private", required_argument, NULL, 'P'},
{"architecture", required_argument, NULL, 'm'},
{"archive-headers", no_argument, NULL, 'a'},
+#ifdef ENABLE_LIBCTF
+ {"ctf", optional_argument, NULL, OPTION_CTF},
+ {"ctf-parent", required_argument, NULL, OPTION_CTF_PARENT},
+#endif
{"debugging", no_argument, NULL, 'g'},
{"debugging-tags", no_argument, NULL, 'e'},
{"demangle", optional_argument, NULL, 'C'},
{"disassemble", optional_argument, NULL, 'd'},
{"disassemble-all", no_argument, NULL, 'D'},
- {"disassembler-options", required_argument, NULL, 'M'},
{"disassemble-zeroes", no_argument, NULL, 'z'},
+ {"disassembler-options", required_argument, NULL, 'M'},
+ {"dwarf", optional_argument, NULL, OPTION_DWARF},
+ {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK},
+ {"dwarf-depth", required_argument, 0, OPTION_DWARF_DEPTH},
+ {"dwarf-start", required_argument, 0, OPTION_DWARF_START},
{"dynamic-reloc", no_argument, NULL, 'R'},
{"dynamic-syms", no_argument, NULL, 'T'},
{"endian", required_argument, NULL, OPTION_ENDIAN},
{"full-contents", no_argument, NULL, 's'},
{"headers", no_argument, NULL, 'h'},
{"help", no_argument, NULL, 'H'},
+ {"include", required_argument, NULL, 'I'},
{"info", no_argument, NULL, 'i'},
+ {"inlines", no_argument, 0, OPTION_INLINES},
+ {"insn-width", required_argument, NULL, OPTION_INSN_WIDTH},
{"line-numbers", no_argument, NULL, 'l'},
- {"no-show-raw-insn", no_argument, &show_raw_insn, -1},
{"no-addresses", no_argument, &no_addresses, 1},
- {"process-links", no_argument, &process_links, true},
+ {"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
+ {"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
+ {"no-show-raw-insn", no_argument, &show_raw_insn, -1},
+ {"prefix", required_argument, NULL, OPTION_PREFIX},
{"prefix-addresses", no_argument, &prefix_addresses, 1},
+ {"prefix-strip", required_argument, NULL, OPTION_PREFIX_STRIP},
+ {"private", required_argument, NULL, 'P'},
+ {"private-headers", no_argument, NULL, 'p'},
+ {"process-links", no_argument, &process_links, true},
{"recurse-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
{"recursion-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
- {"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
- {"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
{"reloc", no_argument, NULL, 'r'},
{"section", required_argument, NULL, 'j'},
{"section-headers", no_argument, NULL, 'h'},
+ {"sframe", optional_argument, NULL, OPTION_SFRAME},
+ {"show-all-symbols", no_argument, &show_all_symbols, 1},
{"show-raw-insn", no_argument, &show_raw_insn, 1},
{"source", no_argument, NULL, 'S'},
{"source-comment", optional_argument, NULL, OPTION_SOURCE_COMMENT},
{"special-syms", no_argument, &dump_special_syms, 1},
- {"include", required_argument, NULL, 'I'},
- {"dwarf", optional_argument, NULL, OPTION_DWARF},
-#ifdef ENABLE_LIBCTF
- {"ctf", required_argument, NULL, OPTION_CTF},
- {"ctf-parent", required_argument, NULL, OPTION_CTF_PARENT},
-#endif
{"stabs", no_argument, NULL, 'G'},
{"start-address", required_argument, NULL, OPTION_START_ADDRESS},
{"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS},
{"syms", no_argument, NULL, 't'},
{"target", required_argument, NULL, 'b'},
+ {"unicode", required_argument, NULL, 'U'},
{"version", no_argument, NULL, 'V'},
- {"wide", no_argument, NULL, 'w'},
- {"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},
- {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK},
- {"inlines", no_argument, 0, OPTION_INLINES},
{"visualize-jumps", optional_argument, 0, OPTION_VISUALIZE_JUMPS},
- {0, no_argument, 0, 0}
+ {"wide", no_argument, NULL, 'w'},
+ {"disassembler-color", required_argument, NULL, OPTION_DISASSEMBLER_COLOR},
+ {NULL, no_argument, NULL, 0}
};
\f
static void
-nonfatal (const char *msg)
+my_bfd_nonfatal (const char *msg)
{
bfd_nonfatal (msg);
exit_status = 1;
}
+/* Convert a potential UTF-8 encoded sequence in IN into characters in OUT.
+ The conversion format is controlled by the unicode_display variable.
+ Returns the number of characters added to OUT.
+ Returns the number of bytes consumed from IN in CONSUMED.
+ Always consumes at least one byte and displays at least one character. */
+
+static unsigned int
+display_utf8 (const unsigned char * in, char * out, unsigned int * consumed)
+{
+ char * orig_out = out;
+ unsigned int nchars = 0;
+ unsigned int j;
+
+ if (unicode_display == unicode_default)
+ goto invalid;
+
+ if (in[0] < 0xc0)
+ goto invalid;
+
+ if ((in[1] & 0xc0) != 0x80)
+ goto invalid;
+
+ if ((in[0] & 0x20) == 0)
+ {
+ nchars = 2;
+ goto valid;
+ }
+
+ if ((in[2] & 0xc0) != 0x80)
+ goto invalid;
+
+ if ((in[0] & 0x10) == 0)
+ {
+ nchars = 3;
+ goto valid;
+ }
+
+ if ((in[3] & 0xc0) != 0x80)
+ goto invalid;
+
+ nchars = 4;
+
+ valid:
+ switch (unicode_display)
+ {
+ case unicode_locale:
+ /* Copy the bytes into the output buffer as is. */
+ memcpy (out, in, nchars);
+ out += nchars;
+ break;
+
+ case unicode_invalid:
+ case unicode_hex:
+ out += sprintf (out, "%c", unicode_display == unicode_hex ? '<' : '{');
+ out += sprintf (out, "0x");
+ for (j = 0; j < nchars; j++)
+ out += sprintf (out, "%02x", in [j]);
+ out += sprintf (out, "%c", unicode_display == unicode_hex ? '>' : '}');
+ break;
+
+ case unicode_highlight:
+ if (isatty (1))
+ out += sprintf (out, "\x1B[31;47m"); /* Red. */
+ /* Fall through. */
+ case unicode_escape:
+ switch (nchars)
+ {
+ case 2:
+ out += sprintf (out, "\\u%02x%02x",
+ ((in[0] & 0x1c) >> 2),
+ ((in[0] & 0x03) << 6) | (in[1] & 0x3f));
+ break;
+
+ case 3:
+ out += sprintf (out, "\\u%02x%02x",
+ ((in[0] & 0x0f) << 4) | ((in[1] & 0x3c) >> 2),
+ ((in[1] & 0x03) << 6) | ((in[2] & 0x3f)));
+ break;
+
+ case 4:
+ out += sprintf (out, "\\u%02x%02x%02x",
+ ((in[0] & 0x07) << 6) | ((in[1] & 0x3c) >> 2),
+ ((in[1] & 0x03) << 6) | ((in[2] & 0x3c) >> 2),
+ ((in[2] & 0x03) << 6) | ((in[3] & 0x3f)));
+ break;
+ default:
+ /* URG. */
+ break;
+ }
+
+ if (unicode_display == unicode_highlight && isatty (1))
+ out += sprintf (out, "\033[0m"); /* Default colour. */
+ break;
+
+ default:
+ /* URG */
+ break;
+ }
+
+ * consumed = nchars;
+ return out - orig_out;
+
+ invalid:
+ /* Not a valid UTF-8 sequence. */
+ *out = *in;
+ * consumed = 1;
+ return 1;
+}
+
/* Returns a version of IN with any control characters
replaced by escape sequences. Uses a static buffer
- if necessary. */
+ if necessary.
+
+ If unicode display is enabled, then also handles the
+ conversion of unicode characters. */
static const char *
sanitize_string (const char * in)
of cases it will not be needed. */
do
{
- char c = *in++;
+ unsigned char c = *in++;
if (c == 0)
return original;
if (ISCNTRL (c))
break;
+
+ if (unicode_display != unicode_default && c >= 0xc0)
+ break;
}
while (1);
/* Copy the input, translating as needed. */
in = original;
- if (buffer_len < (strlen (in) * 2))
+ if (buffer_len < (strlen (in) * 9))
{
free ((void *) buffer);
- buffer_len = strlen (in) * 2;
+ buffer_len = strlen (in) * 9;
buffer = xmalloc (buffer_len + 1);
}
out = buffer;
do
{
- char c = *in++;
+ unsigned char c = *in++;
if (c == 0)
break;
- if (!ISCNTRL (c))
- *out++ = c;
- else
+ if (ISCNTRL (c))
{
*out++ = '^';
*out++ = c + 0x40;
}
+ else if (unicode_display != unicode_default && c >= 0xc0)
+ {
+ unsigned int num_consumed;
+
+ out += display_utf8 ((const unsigned char *)(in - 1), out, & num_consumed);
+ in += num_consumed - 1;
+ }
+ else
+ *out++ = c;
}
while (1);
if (wide_output)
bfd_map_over_sections (abfd, find_longest_section_name,
- &max_section_name_length);
+ &max_section_name_length);
printf (_("Idx %-*s Size %-*s%-*sFile off Algn"),
max_section_name_length, "Name",
printf ("\n");
bfd_map_over_sections (abfd, dump_section_header,
- &max_section_name_length);
+ &max_section_name_length);
}
\f
static asymbol **
slurp_symtab (bfd *abfd)
{
- asymbol **sy = NULL;
- long storage;
-
+ symcount = 0;
if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
- {
- symcount = 0;
- return NULL;
- }
+ return NULL;
- storage = bfd_get_symtab_upper_bound (abfd);
+ long storage = bfd_get_symtab_upper_bound (abfd);
if (storage < 0)
{
- non_fatal (_("failed to read symbol table from: %s"), bfd_get_filename (abfd));
- bfd_fatal (_("error message was"));
+ non_fatal (_("failed to read symbol table from: %s"),
+ bfd_get_filename (abfd));
+ my_bfd_nonfatal (_("error message was"));
}
- if (storage)
- {
- off_t filesize = bfd_get_file_size (abfd);
-
- /* qv PR 24707. */
- if (filesize > 0
- && filesize < storage
- /* The MMO file format supports its own special compression
- technique, so its sections can be larger than the file size. */
- && bfd_get_flavour (abfd) != bfd_target_mmo_flavour)
- {
- bfd_nonfatal_message (bfd_get_filename (abfd), abfd, NULL,
- _("error: symbol table size (%#lx) "
- "is larger than filesize (%#lx)"),
- storage, (long) filesize);
- exit_status = 1;
- symcount = 0;
- return NULL;
- }
-
- sy = (asymbol **) xmalloc (storage);
- }
+ if (storage <= 0)
+ return NULL;
+ asymbol **sy = (asymbol **) xmalloc (storage);
symcount = bfd_canonicalize_symtab (abfd, sy);
if (symcount < 0)
- bfd_fatal (bfd_get_filename (abfd));
+ {
+ my_bfd_nonfatal (bfd_get_filename (abfd));
+ free (sy);
+ sy = NULL;
+ symcount = 0;
+ }
return sy;
}
static asymbol **
slurp_dynamic_symtab (bfd *abfd)
{
- asymbol **sy = NULL;
- long storage;
-
- storage = bfd_get_dynamic_symtab_upper_bound (abfd);
+ dynsymcount = 0;
+ long storage = bfd_get_dynamic_symtab_upper_bound (abfd);
if (storage < 0)
{
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;
}
- bfd_fatal (bfd_get_filename (abfd));
+ my_bfd_nonfatal (bfd_get_filename (abfd));
}
- if (storage)
- sy = (asymbol **) xmalloc (storage);
+ if (storage <= 0)
+ return NULL;
+ asymbol **sy = (asymbol **) xmalloc (storage);
dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, sy);
if (dynsymcount < 0)
- bfd_fatal (bfd_get_filename (abfd));
+ {
+ my_bfd_nonfatal (bfd_get_filename (abfd));
+ free (sy);
+ sy = NULL;
+ dynsymcount = 0;
+ }
return sy;
}
return 1;
}
- if (bfd_get_flavour (bfd_asymbol_bfd (a)) == bfd_target_elf_flavour
+ /* Sort larger size ELF symbols before smaller. See PR20337. */
+ bfd_vma asz = 0;
+ if ((a->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0
+ && bfd_get_flavour (bfd_asymbol_bfd (a)) == bfd_target_elf_flavour)
+ asz = ((elf_symbol_type *) a)->internal_elf_sym.st_size;
+ bfd_vma bsz = 0;
+ if ((b->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0
&& bfd_get_flavour (bfd_asymbol_bfd (b)) == bfd_target_elf_flavour)
- {
- bfd_vma asz, bsz;
-
- asz = 0;
- if ((a->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0)
- asz = ((elf_symbol_type *) a)->internal_elf_sym.st_size;
- bsz = 0;
- if ((b->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0)
- bsz = ((elf_symbol_type *) b)->internal_elf_sym.st_size;
- if (asz != bsz)
- return asz > bsz ? -1 : 1;
- }
+ bsz = ((elf_symbol_type *) b)->internal_elf_sym.st_size;
+ if (asz != bsz)
+ return asz > bsz ? -1 : 1;
/* Symbols that start with '.' might be section names, so sort them
after symbols that don't start with '.'. */
if (*p == '\0')
--p;
}
- (*inf->fprintf_func) (inf->stream, "%s", p);
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_address, "%s", p);
}
/* Print the name of a symbol. */
if (inf != NULL)
{
- (*inf->fprintf_func) (inf->stream, "%s", name);
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_symbol, "%s", name);
if (version_string && *version_string != '\0')
- (*inf->fprintf_func) (inf->stream, hidden ? "@%s" : "@@%s",
- version_string);
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_symbol,
+ hidden ? "@%s" : "@@%s",
+ version_string);
}
else
{
if (want_section)
{
/* NB: An object file can have different sections with the same
- section name. Compare compare section pointers if they have
+ section name. Compare compare section pointers if they have
the same owner. */
if (sorted_syms[place]->section->owner == sec->owner
&& sorted_syms[place]->section != sec)
&& vma >= bfd_section_vma (sec)
&& vma < (bfd_section_vma (sec)
+ bfd_section_size (sec) / opb)));
-
+
if (! sym_ok (want_section, abfd, thisplace, sec, inf))
{
long i;
if (rel->address == vma)
{
/* Absolute relocations do not provide a more helpful
- symbolic address. Find a non-absolute relocation
+ symbolic address. Find a non-absolute relocation
with the same address. */
arelent **rel_vma = rel_mid;
for (rel_mid--;
if (!no_addresses)
{
objdump_print_value (vma, inf, skip_zeroes);
- (*inf->fprintf_func) (inf->stream, " ");
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_text, " ");
}
if (sym == NULL)
{
bfd_vma secaddr;
- (*inf->fprintf_func) (inf->stream, "<%s",
- sanitize_string (bfd_section_name (sec)));
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_text,"<");
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_symbol, "%s",
+ sanitize_string (bfd_section_name (sec)));
secaddr = bfd_section_vma (sec);
if (vma < secaddr)
{
- (*inf->fprintf_func) (inf->stream, "-0x");
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_immediate,
+ "-0x");
objdump_print_value (secaddr - vma, inf, true);
}
else if (vma > secaddr)
{
- (*inf->fprintf_func) (inf->stream, "+0x");
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_immediate, "+0x");
objdump_print_value (vma - secaddr, inf, true);
}
- (*inf->fprintf_func) (inf->stream, ">");
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_text, ">");
}
else
{
- (*inf->fprintf_func) (inf->stream, "<");
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_text, "<");
objdump_print_symname (abfd, inf, sym);
;
else if (bfd_asymbol_value (sym) > vma)
{
- (*inf->fprintf_func) (inf->stream, "-0x");
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_immediate,"-0x");
objdump_print_value (bfd_asymbol_value (sym) - vma, inf, true);
}
else if (vma > bfd_asymbol_value (sym))
{
- (*inf->fprintf_func) (inf->stream, "+0x");
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_immediate, "+0x");
objdump_print_value (vma - bfd_asymbol_value (sym), inf, true);
}
- (*inf->fprintf_func) (inf->stream, ">");
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_text, ">");
}
if (display_file_offsets)
- inf->fprintf_func (inf->stream, _(" (File Offset: 0x%lx)"),
- (long int)(sec->filepos + (vma - sec->vma)));
+ inf->fprintf_styled_func (inf->stream, dis_style_text,
+ _(" (File Offset: 0x%lx)"),
+ (long int)(sec->filepos + (vma - sec->vma)));
}
/* Print an address (VMA), symbolically if possible.
{
if (!no_addresses)
{
- (*inf->fprintf_func) (inf->stream, "0x");
+ (*inf->fprintf_styled_func) (inf->stream, dis_style_address, "0x");
objdump_print_value (vma, inf, skip_zeroes);
}
if (display_file_offsets)
- inf->fprintf_func (inf->stream, _(" (File Offset: 0x%lx)"),
- (long int) (inf->section->filepos
- + (vma - inf->section->vma)));
+ inf->fprintf_styled_func (inf->stream, dis_style_text,
+ _(" (File Offset: 0x%lx)"),
+ (long int) (inf->section->filepos
+ + (vma - inf->section->vma)));
return;
}
#define SHOW_PRECEDING_CONTEXT_LINES (5)
-/* Read a complete file into memory. */
+#if HAVE_LIBDEBUGINFOD
+/* Return a hex string represention of the build-id. */
+
+unsigned char *
+get_build_id (void * data)
+{
+ unsigned i;
+ char * build_id_str;
+ bfd * abfd = (bfd *) data;
+ const struct bfd_build_id * build_id;
+
+ build_id = abfd->build_id;
+ if (build_id == NULL)
+ return NULL;
+
+ build_id_str = malloc (build_id->size * 2 + 1);
+ if (build_id_str == NULL)
+ return NULL;
+
+ for (i = 0; i < build_id->size; i++)
+ sprintf (build_id_str + (i * 2), "%02x", build_id->data[i]);
+ build_id_str[build_id->size * 2] = '\0';
+
+ return (unsigned char *) build_id_str;
+}
+
+/* Search for a separate debug file matching ABFD's build-id. */
+
+static bfd *
+find_separate_debug (const bfd * abfd)
+{
+ const struct bfd_build_id * build_id = abfd->build_id;
+ separate_info * i = first_separate_info;
+
+ if (build_id == NULL || i == NULL)
+ return NULL;
+
+ while (i != NULL)
+ {
+ const bfd * i_bfd = (bfd *) i->handle;
+
+ if (abfd != NULL && i_bfd->build_id != NULL)
+ {
+ const unsigned char * data = i_bfd->build_id->data;
+ size_t size = i_bfd->build_id->size;
+
+ if (size == build_id->size
+ && memcmp (data, build_id->data, size) == 0)
+ return (bfd *) i->handle;
+ }
+
+ i = i->next;
+ }
+
+ return NULL;
+}
+
+/* Search for a separate debug file matching ABFD's .gnu_debugaltlink
+ build-id. */
+
+static bfd *
+find_alt_debug (const bfd * abfd)
+{
+ size_t namelen;
+ size_t id_len;
+ const char * name;
+ struct dwarf_section * section;
+ const struct bfd_build_id * build_id = abfd->build_id;
+ separate_info * i = first_separate_info;
+
+ if (i == NULL
+ || build_id == NULL
+ || !load_debug_section (gnu_debugaltlink, (void *) abfd))
+ return NULL;
+
+ section = &debug_displays[gnu_debugaltlink].section;
+ if (section == NULL)
+ return NULL;
+
+ name = (const char *) section->start;
+ namelen = strnlen (name, section->size) + 1;
+ if (namelen == 1)
+ return NULL;
+ if (namelen >= section->size)
+ return NULL;
+
+ id_len = section->size - namelen;
+ if (id_len < 0x14)
+ return NULL;
+
+ /* Compare the .gnu_debugaltlink build-id with the build-ids of the
+ known separate_info files. */
+ while (i != NULL)
+ {
+ const bfd * i_bfd = (bfd *) i->handle;
+
+ if (i_bfd != NULL && i_bfd->build_id != NULL)
+ {
+ const unsigned char * data = i_bfd->build_id->data;
+ size_t size = i_bfd->build_id->size;
+
+ if (id_len == size
+ && memcmp (section->start + namelen, data, size) == 0)
+ return (bfd *) i->handle;
+ }
+
+ i = i->next;
+ }
+
+ return NULL;
+}
+
+#endif /* HAVE_LIBDEBUGINFOD */
+
+/* Reads the contents of file FN into memory. Returns a pointer to the buffer.
+ Also returns the size of the buffer in SIZE_RETURN and a filled out
+ stat structure in FST_RETURN. Returns NULL upon failure. */
static const char *
-slurp_file (const char *fn, size_t *size, struct stat *fst)
+slurp_file (const char * fn,
+ size_t * size_return,
+ struct stat * fst_return,
+ bfd * abfd ATTRIBUTE_UNUSED)
{
#ifdef HAVE_MMAP
- int ps = getpagesize ();
+ int ps;
size_t msize;
#endif
const char *map;
- int fd = open (fn, O_RDONLY | O_BINARY);
+ int fd;
+
+ /* Paranoia. */
+ if (fn == NULL || * fn == 0 || size_return == NULL || fst_return == NULL)
+ return NULL;
+
+ fd = open (fn, O_RDONLY | O_BINARY);
+
+#if HAVE_LIBDEBUGINFOD
+ if (fd < 0 && use_debuginfod && fn[0] == '/' && abfd != NULL)
+ {
+ unsigned char *build_id = get_build_id (abfd);
+
+ if (build_id)
+ {
+ debuginfod_client *client = debuginfod_begin ();
+
+ if (client)
+ {
+ fd = debuginfod_find_source (client, build_id, 0, fn, NULL);
+ debuginfod_end (client);
+ }
+ free (build_id);
+ }
+ }
+#endif
if (fd < 0)
return NULL;
- if (fstat (fd, fst) < 0)
+
+ if (fstat (fd, fst_return) < 0)
{
close (fd);
return NULL;
}
- *size = fst->st_size;
+
+ *size_return = fst_return->st_size;
+
#ifdef HAVE_MMAP
- msize = (*size + ps - 1) & ~(ps - 1);
+ ps = getpagesize ();
+ msize = (*size_return + ps - 1) & ~(ps - 1);
map = mmap (NULL, msize, PROT_READ, MAP_SHARED, fd, 0);
if (map != (char *) -1L)
{
return map;
}
#endif
- map = (const char *) malloc (*size);
- if (!map || (size_t) read (fd, (char *) map, *size) != *size)
+
+ map = (const char *) malloc (*size_return);
+ if (!map || (size_t) read (fd, (char *) map, *size_return) != *size_return)
{
free ((void *) map);
map = NULL;
}
/* Tries to open MODNAME, and if successful adds a node to print_files
- linked list and returns that node. Returns NULL on failure. */
+ linked list and returns that node. Also fills in the stat structure
+ pointed to by FST_RETURN. Returns NULL on failure. */
static struct print_file_list *
-try_print_file_open (const char *origname, const char *modname, struct stat *fst)
+try_print_file_open (const char * origname,
+ const char * modname,
+ struct stat * fst_return,
+ bfd * abfd)
{
struct print_file_list *p;
p = (struct print_file_list *) xmalloc (sizeof (struct print_file_list));
- p->map = slurp_file (modname, &p->mapsize, fst);
+ p->map = slurp_file (modname, &p->mapsize, fst_return, abfd);
if (p->map == NULL)
{
free (p);
struct stat fst;
int i;
- p = try_print_file_open (filename, filename, &fst);
+ p = try_print_file_open (filename, filename, &fst, abfd);
if (p == NULL)
{
if (include_path_count == 0)
char *modname = concat (include_paths[i], "/", fname,
(const char *) 0);
- p = try_print_file_open (filename, modname, &fst);
+ p = try_print_file_open (filename, modname, &fst, abfd);
if (p)
break;
const char *l;
size_t len;
- --linenum;
if (linenum >= p->maxline)
return;
l = p->linemap [linenum];
{
if (p->map == NULL)
return;
- while (start <= end)
+ if (start != 0)
+ --start;
+ while (start < end)
{
print_line (p, start);
start++;
if (! with_line_numbers && ! with_source_code)
return;
+#ifdef HAVE_LIBDEBUGINFOD
+ {
+ bfd *debug_bfd;
+ const char *alt_filename = NULL;
+
+ if (use_debuginfod)
+ {
+ bfd *alt_bfd;
+
+ /* PR 29075: Check for separate debuginfo and .gnu_debugaltlink files.
+ They need to be passed to bfd_find_nearest_line_with_alt in case they
+ were downloaded from debuginfod. Otherwise libbfd will attempt to
+ search for them and fail to locate them. */
+ debug_bfd = find_separate_debug (abfd);
+ if (debug_bfd == NULL)
+ debug_bfd = abfd;
+
+ alt_bfd = find_alt_debug (debug_bfd);
+ if (alt_bfd != NULL)
+ alt_filename = bfd_get_filename (alt_bfd);
+ }
+ else
+ debug_bfd = abfd;
+
+ bfd_set_error (bfd_error_no_error);
+ if (! bfd_find_nearest_line_with_alt (debug_bfd, alt_filename,
+ section, syms,
+ addr_offset, &filename,
+ &functionname, &linenumber,
+ &discriminator))
+ {
+ if (bfd_get_error () == bfd_error_no_error)
+ return;
+ if (! bfd_find_nearest_line_discriminator (abfd, section, syms,
+ addr_offset, &filename,
+ &functionname, &linenumber,
+ &discriminator))
+ return;
+ }
+ }
+#else
if (! bfd_find_nearest_line_discriminator (abfd, section, syms, addr_offset,
&filename, &functionname,
&linenumber, &discriminator))
return;
+#endif
if (filename != NULL && *filename == '\0')
filename = NULL;
{
/* Demangle the name. */
demangle_alloc = bfd_demangle (abfd, functionname,
- demangle_flags);
+ demangle_flags);
}
/* Demangling adds trailing parens, so don't print those. */
strcpy (prev_functionname, functionname);
}
- if (linenumber > 0 && linenumber != prev_line)
- prev_line = linenumber;
-
- if (discriminator != prev_discriminator)
- prev_discriminator = discriminator;
-
- if (path)
- free (path);
+ if (linenumber > 0 && linenumber != prev_line)
+ prev_line = linenumber;
+
+ if (discriminator != prev_discriminator)
+ prev_discriminator = discriminator;
+
+ if (path)
+ free (path);
+}
+
+/* Pseudo FILE object for strings. */
+typedef struct
+{
+ char *buffer;
+ size_t pos;
+ size_t alloc;
+} SFILE;
+
+/* sprintf to a "stream". */
+
+static int ATTRIBUTE_PRINTF_2
+objdump_sprintf (SFILE *f, const char *format, ...)
+{
+ size_t n;
+ va_list args;
+
+ 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;
+}
+
+/* Return an integer greater than, or equal to zero, representing the color
+ for STYLE, or -1 if no color should be used. */
+
+static int
+objdump_color_for_disassembler_style (enum disassembler_style style)
+{
+ int color = -1;
+
+ if (style == dis_style_comment_start)
+ disassembler_in_comment = true;
+
+ if (disassembler_color == on)
+ {
+ if (disassembler_in_comment)
+ return color;
+
+ switch (style)
+ {
+ case dis_style_symbol:
+ color = 32;
+ break;
+ case dis_style_assembler_directive:
+ case dis_style_sub_mnemonic:
+ case dis_style_mnemonic:
+ color = 33;
+ break;
+ case dis_style_register:
+ color = 34;
+ break;
+ case dis_style_address:
+ case dis_style_address_offset:
+ case dis_style_immediate:
+ color = 35;
+ break;
+ default:
+ case dis_style_text:
+ color = -1;
+ break;
+ }
+ }
+ else if (disassembler_color == extended)
+ {
+ if (disassembler_in_comment)
+ return 250;
+
+ switch (style)
+ {
+ case dis_style_symbol:
+ color = 40;
+ break;
+ case dis_style_assembler_directive:
+ case dis_style_sub_mnemonic:
+ case dis_style_mnemonic:
+ color = 142;
+ break;
+ case dis_style_register:
+ color = 27;
+ break;
+ case dis_style_address:
+ case dis_style_address_offset:
+ case dis_style_immediate:
+ color = 134;
+ break;
+ default:
+ case dis_style_text:
+ color = -1;
+ break;
+ }
+ }
+ else if (disassembler_color != off)
+ bfd_fatal (_("disassembly color not correctly selected"));
+
+ return color;
}
-/* Pseudo FILE object for strings. */
-typedef struct
-{
- char *buffer;
- size_t pos;
- size_t alloc;
-} SFILE;
-
-/* sprintf to a "stream". */
+/* Like objdump_sprintf, but add in escape sequences to highlight the
+ content according to STYLE. */
-static int ATTRIBUTE_PRINTF_2
-objdump_sprintf (SFILE *f, const char *format, ...)
+static int ATTRIBUTE_PRINTF_3
+objdump_styled_sprintf (SFILE *f, enum disassembler_style style,
+ const char *format, ...)
{
size_t n;
va_list args;
+ int color = objdump_color_for_disassembler_style (style);
+
+ if (color >= 0)
+ {
+ while (1)
+ {
+ size_t space = f->alloc - f->pos;
+
+ if (disassembler_color == on)
+ n = snprintf (f->buffer + f->pos, space, "\033[%dm", color);
+ else
+ n = snprintf (f->buffer + f->pos, space, "\033[38;5;%dm", color);
+ if (space > n)
+ break;
+
+ f->alloc = (f->alloc + n) * 2;
+ f->buffer = (char *) xrealloc (f->buffer, f->alloc);
+ }
+ f->pos += n;
+ }
while (1)
{
}
f->pos += n;
+ if (color >= 0)
+ {
+ while (1)
+ {
+ size_t space = f->alloc - f->pos;
+
+ n = snprintf (f->buffer + f->pos, space, "\033[0m");
+
+ if (space > n)
+ break;
+
+ f->alloc = (f->alloc + n) * 2;
+ f->buffer = (char *) xrealloc (f->buffer, f->alloc);
+ }
+ f->pos += n;
+ }
+
return n;
}
+/* We discard the styling information here. This function is only used
+ when objdump is printing auxiliary information, the symbol headers, and
+ disassembly address, or the bytes of the disassembled instruction. We
+ don't (currently) apply styling to any of this stuff, so, for now, just
+ print the content with no additional style added. */
+
+static int ATTRIBUTE_PRINTF_3
+fprintf_styled (FILE *f, enum disassembler_style style ATTRIBUTE_UNUSED,
+ const char *fmt, ...)
+{
+ int res;
+ va_list ap;
+
+ va_start (ap, fmt);
+ res = vfprintf (f, fmt, ap);
+ va_end (ap);
+
+ return res;
+}
+
/* Code for generating (colored) diagrams of control flow start and end
points. */
sfile.pos = 0;
inf->insn_info_valid = 0;
- inf->fprintf_func = (fprintf_ftype) objdump_sprintf;
- inf->stream = &sfile;
+ disassemble_set_printf (inf, &sfile, (fprintf_ftype) objdump_sprintf,
+ (fprintf_styled_ftype) objdump_styled_sprintf);
addr_offset = start_offset;
while (addr_offset < stop_offset)
inf->bytes_per_line = 0;
inf->bytes_per_chunk = 0;
inf->flags = ((disassemble_all ? DISASSEMBLE_DATA : 0)
- | (wide_output ? WIDE_OUTPUT : 0));
+ | (wide_output ? WIDE_OUTPUT : 0));
if (machine)
inf->flags |= USER_SPECIFIED_MACHINE_TYPE;
/* Extract jump information. */
inf->insn_info_valid = 0;
+ disassembler_in_comment = false;
octets = (*disassemble_fn) (section->vma + addr_offset, inf);
/* Test if a jump was detected. */
if (inf->insn_info_valid
addr_offset += octets / opb;
}
- inf->fprintf_func = (fprintf_ftype) fprintf;
- inf->stream = stdout;
-
+ disassemble_set_printf (inf, (void *) stdout, (fprintf_ftype) fprintf,
+ (fprintf_styled_ftype) fprintf_styled);
free (sfile.buffer);
/* Merge jumps. */
return 1;
}
+/* Like null_print, but takes the extra STYLE argument. As this is not
+ going to print anything, the extra argument is just ignored. */
+
+static int
+null_styled_print (const void * stream ATTRIBUTE_UNUSED,
+ enum disassembler_style style ATTRIBUTE_UNUSED,
+ const char * format ATTRIBUTE_UNUSED, ...)
+{
+ return 1;
+}
+
/* Print out jump visualization. */
static void
int insn_size;
sfile.pos = 0;
- inf->fprintf_func = (fprintf_ftype) objdump_sprintf;
- inf->stream = &sfile;
+ disassemble_set_printf
+ (inf, &sfile, (fprintf_ftype) objdump_sprintf,
+ (fprintf_styled_ftype) objdump_styled_sprintf);
inf->bytes_per_line = 0;
inf->bytes_per_chunk = 0;
inf->flags = ((disassemble_all ? DISASSEMBLE_DATA : 0)
twice, but we only do this when there is a high
probability that there is a reloc that will
affect the instruction. */
- inf->fprintf_func = (fprintf_ftype) null_print;
+ disassemble_set_printf
+ (inf, inf->stream, (fprintf_ftype) null_print,
+ (fprintf_styled_ftype) null_styled_print);
insn_size = disassemble_fn (section->vma
+ addr_offset, inf);
- inf->fprintf_func = (fprintf_ftype) objdump_sprintf;
+ disassemble_set_printf
+ (inf, inf->stream,
+ (fprintf_ftype) objdump_sprintf,
+ (fprintf_styled_ftype) objdump_styled_sprintf);
}
}
inf->stop_vma = section->vma + stop_offset;
inf->stop_offset = stop_offset;
+ disassembler_in_comment = false;
insn_size = (*disassemble_fn) (section->vma + addr_offset, inf);
octets = insn_size;
inf->stop_vma = 0;
- inf->fprintf_func = (fprintf_ftype) fprintf;
- inf->stream = stdout;
+ disassemble_set_printf (inf, stdout, (fprintf_ftype) fprintf,
+ (fprintf_styled_ftype) fprintf_styled);
if (insn_width == 0 && inf->bytes_per_line != 0)
octets_per_line = inf->bytes_per_line;
if (insn_size < (int) opb)
next_sym
} loop_until;
- /* Sections that do not contain machine
- code are not normally disassembled. */
- if (! disassemble_all
- && only_list == NULL
- && ((section->flags & (SEC_CODE | SEC_HAS_CONTENTS))
- != (SEC_CODE | SEC_HAS_CONTENTS)))
- return;
+ if (only_list == NULL)
+ {
+ /* Sections that do not contain machine
+ code are not normally disassembled. */
+ if ((section->flags & SEC_HAS_CONTENTS) == 0)
+ return;
- if (! process_section_p (section))
+ if (! disassemble_all
+ && (section->flags & SEC_CODE) == 0)
+ return;
+ }
+ else if (!process_section_p (section))
return;
datasize = bfd_section_size (section);
relsize = bfd_get_reloc_upper_bound (abfd, section);
if (relsize < 0)
- bfd_fatal (bfd_get_filename (abfd));
+ my_bfd_nonfatal (bfd_get_filename (abfd));
if (relsize > 0)
{
- rel_ppstart = rel_pp = (arelent **) xmalloc (relsize);
+ rel_pp = (arelent **) xmalloc (relsize);
rel_count = bfd_canonicalize_reloc (abfd, section, rel_pp, syms);
if (rel_count < 0)
- bfd_fatal (bfd_get_filename (abfd));
-
- /* Sort the relocs by address. */
- qsort (rel_pp, rel_count, sizeof (arelent *), compare_relocs);
+ {
+ my_bfd_nonfatal (bfd_get_filename (abfd));
+ free (rel_pp);
+ rel_pp = NULL;
+ rel_count = 0;
+ }
+ else if (rel_count > 1)
+ /* Sort the relocs by address. */
+ qsort (rel_pp, rel_count, sizeof (arelent *), compare_relocs);
+ rel_ppstart = rel_pp;
}
}
}
/* Find the nearest symbol forwards from our current position. */
paux->require_sec = true;
sym = (asymbol *) find_symbol_for_address (section->vma + addr_offset,
- (struct disassemble_info *) inf,
- &place);
+ (struct disassemble_info *) inf,
+ &place);
paux->require_sec = false;
/* PR 9774: If the target used signed addresses then we must make
{
do_print = true;
+ /* Skip over the relocs belonging to addresses below the
+ symbol address. */
+ const bfd_vma sym_offset = bfd_asymbol_value (sym) - section->vma;
+ while (rel_pp < rel_ppend &&
+ (*rel_pp)->address - rel_offset < sym_offset)
+ ++rel_pp;
+
if (sym->flags & BSF_FUNCTION)
{
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
objdump_print_addr_with_sym (abfd, section, sym, addr,
pinfo, false);
pinfo->fprintf_func (pinfo->stream, ":\n");
+
+ if (sym != NULL && show_all_symbols)
+ {
+ for (++place; place < sorted_symcount; place++)
+ {
+ sym = sorted_syms[place];
+
+ if (bfd_asymbol_value (sym) != addr)
+ break;
+ if (! pinfo->symbol_is_valid (sym, pinfo))
+ continue;
+ if (strcmp (bfd_section_name (sym->section), bfd_section_name (section)) != 0)
+ break;
+
+ objdump_print_addr_with_sym (abfd, section, sym, addr, pinfo, false);
+ pinfo->fprintf_func (pinfo->stream, ":\n");
+ }
+ }
}
if (sym != NULL && bfd_asymbol_value (sym) > addr)
sf.alloc = strlen (sym->name) + 40;
sf.buffer = (char*) xmalloc (sf.alloc);
sf.pos = 0;
- di.fprintf_func = (fprintf_ftype) objdump_sprintf;
- di.stream = &sf;
+ disassemble_set_printf
+ (&di, &sf, (fprintf_ftype) objdump_sprintf,
+ (fprintf_styled_ftype) objdump_styled_sprintf);
objdump_print_symname (abfd, &di, sym);
because that will screw up the relocs. */
sorted_symcount = symcount ? symcount : dynsymcount;
sorted_syms = (asymbol **) xmalloc ((sorted_symcount + synthcount)
- * sizeof (asymbol *));
+ * sizeof (asymbol *));
if (sorted_symcount != 0)
{
memcpy (sorted_syms, symcount ? syms : dynsyms,
++sorted_symcount;
}
- init_disassemble_info (&disasm_info, stdout, (fprintf_ftype) fprintf);
-
+ init_disassemble_info (&disasm_info, stdout, (fprintf_ftype) fprintf,
+ (fprintf_styled_ftype) fprintf_styled);
disasm_info.application_data = (void *) &aux;
aux.abfd = abfd;
aux.require_sec = false;
const bfd_arch_info_type *inf = bfd_scan_arch (machine);
if (inf == NULL)
- fatal (_("can't use supplied machine %s"), machine);
-
- abfd->arch_info = inf;
+ {
+ non_fatal (_("can't use supplied machine %s"), machine);
+ exit_status = 1;
+ }
+ else
+ abfd->arch_info = inf;
}
if (endian != BFD_ENDIAN_UNKNOWN)
/* Pre-load the dynamic relocs as we may need them during the disassembly. */
long relsize = bfd_get_dynamic_reloc_upper_bound (abfd);
- if (relsize < 0 && dump_dynamic_reloc_info)
- bfd_fatal (bfd_get_filename (abfd));
-
if (relsize > 0)
{
disasm_info.dynrelbuf = (arelent **) xmalloc (relsize);
disasm_info.dynrelcount
= bfd_canonicalize_dynamic_reloc (abfd, disasm_info.dynrelbuf, dynsyms);
if (disasm_info.dynrelcount < 0)
- bfd_fatal (bfd_get_filename (abfd));
-
- /* Sort the relocs by address. */
- qsort (disasm_info.dynrelbuf, disasm_info.dynrelcount, sizeof (arelent *),
- compare_relocs);
+ {
+ my_bfd_nonfatal (bfd_get_filename (abfd));
+ free (disasm_info.dynrelbuf);
+ disasm_info.dynrelbuf = NULL;
+ disasm_info.dynrelcount = 0;
+ }
+ else if (disasm_info.dynrelcount > 1)
+ /* Sort the relocs by address. */
+ qsort (disasm_info.dynrelbuf, disasm_info.dynrelcount,
+ sizeof (arelent *), compare_relocs);
}
disasm_info.symtab = sorted_syms;
section->size = bfd_section_size (sec);
/* PR 24360: On 32-bit hosts sizeof (size_t) < sizeof (bfd_size_type). */
alloced = amt = section->size + 1;
- if (alloced != amt || alloced == 0)
+ if (alloced != amt
+ || alloced == 0
+ || (bfd_get_size (abfd) != 0 && alloced >= bfd_get_size (abfd)))
{
section->start = NULL;
free_debug_section (debug);
- printf (_("\nSection '%s' has an invalid size: %#llx.\n"),
+ printf (_("\nSection '%s' has an invalid size: %#" PRIx64 ".\n"),
sanitize_string (section->name),
- (unsigned long long) section->size);
+ section->size);
return false;
}
if (reloc_size > 0)
{
- unsigned long reloc_count;
+ long reloc_count;
arelent **relocs;
relocs = (arelent **) xmalloc (reloc_size);
- reloc_count = bfd_canonicalize_reloc (abfd, sec, relocs, NULL);
- if (reloc_count == 0)
+ reloc_count = bfd_canonicalize_reloc (abfd, sec, relocs, syms);
+ if (reloc_count <= 0)
free (relocs);
else
{
}
bool
-reloc_at (struct dwarf_section * dsec, dwarf_vma offset)
+reloc_at (struct dwarf_section * dsec, uint64_t offset)
{
arelent ** relocs;
arelent * rp;
asection *sec;
const char *name;
+ if (!dump_any_debugging)
+ return false;
+
/* If it is already loaded, do nothing. */
if (section->start != NULL)
{
section->start = NULL;
section->address = 0;
section->size = 0;
+ free ((char*) section->reloc_info);
+ section->reloc_info = NULL;
+ section->num_relocs= 0;
}
void
if (! bfd_check_format (data, bfd_object))
return NULL;
-
- return data;
-}
-
-#if HAVE_LIBDEBUGINFOD
-/* Return a hex string represention of the build-id. */
-
-unsigned char *
-get_build_id (void * data)
-{
- unsigned i;
- char * build_id_str;
- bfd * abfd = (bfd *) data;
- const struct bfd_build_id * build_id;
-
- build_id = abfd->build_id;
- if (build_id == NULL)
- return NULL;
-
- build_id_str = malloc (build_id->size * 2 + 1);
- if (build_id_str == NULL)
- return NULL;
-
- for (i = 0; i < build_id->size; i++)
- sprintf (build_id_str + (i * 2), "%02x", build_id->data[i]);
- build_id_str[build_id->size * 2] = '\0';
- return (unsigned char *)build_id_str;
+ return data;
}
-#endif /* HAVE_LIBDEBUGINFOD */
static void
dump_dwarf_section (bfd *abfd, asection *section,
- void *arg ATTRIBUTE_UNUSED)
+ void *arg)
{
const char *name = bfd_section_name (section);
const char *match;
int i;
+ bool is_mainfile = *(bool *) arg;
if (*name == 0)
return;
+ if (!is_mainfile && !process_links
+ && (section->flags & SEC_DEBUGGING) == 0)
+ return;
+
if (startswith (name, ".gnu.linkonce.wi."))
match = ".debug_info";
else
else
sec->name = sec->xcoff_name;
if (load_specific_debug_section ((enum dwarf_section_display_enum) i,
- section, abfd))
+ section, abfd))
{
debug_displays [i].display (sec, abfd);
/* Dump the dwarf debugging information. */
static void
-dump_dwarf (bfd *abfd)
+dump_dwarf (bfd *abfd, bool is_mainfile)
{
/* The byte_get pointer should have been set at the start of dump_bfd(). */
if (byte_get == NULL)
init_dwarf_regnames_by_bfd_arch_and_mach (bfd_get_arch (abfd),
bfd_get_mach (abfd));
- bfd_map_over_sections (abfd, dump_dwarf_section, NULL);
+ bfd_map_over_sections (abfd, dump_dwarf_section, (void *) &is_mainfile);
}
\f
-/* Read ABFD's stabs section STABSECT_NAME, and return a pointer to
- it. Return NULL on failure. */
+/* Read ABFD's section SECT_NAME into *CONTENTS, and return a pointer to
+ the section. Return NULL on failure. */
-static bfd_byte *
-read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr,
- bfd_size_type *entsize_ptr)
+static asection *
+read_section (bfd *abfd, const char *sect_name, bfd_byte **contents)
{
- asection *stabsect;
- bfd_byte *contents;
-
- stabsect = bfd_get_section_by_name (abfd, sect_name);
- if (stabsect == NULL)
- {
- printf (_("No %s section present\n\n"),
- sanitize_string (sect_name));
- return false;
- }
+ asection *sec;
- if (!bfd_malloc_and_get_section (abfd, stabsect, &contents))
+ *contents = NULL;
+ sec = bfd_get_section_by_name (abfd, sect_name);
+ if (sec == NULL)
{
- non_fatal (_("reading %s section of %s failed: %s"),
- sect_name, bfd_get_filename (abfd),
- bfd_errmsg (bfd_get_error ()));
- exit_status = 1;
- free (contents);
+ printf (_("No %s section present\n\n"), sanitize_string (sect_name));
return NULL;
}
- *size_ptr = bfd_section_size (stabsect);
- if (entsize_ptr)
- *entsize_ptr = stabsect->entsize;
+ if ((bfd_section_flags (sec) & SEC_HAS_CONTENTS) == 0)
+ bfd_set_error (bfd_error_no_contents);
+ else if (bfd_malloc_and_get_section (abfd, sec, contents))
+ return sec;
- return contents;
+ non_fatal (_("reading %s section of %s failed: %s"),
+ sect_name, bfd_get_filename (abfd),
+ bfd_errmsg (bfd_get_error ()));
+ exit_status = 1;
+ return NULL;
}
/* Stabs entries use a 12 byte format:
bfd_byte *stabp, *stabs_end;
stabp = stabs;
- stabs_end = stabp + stab_size;
+ stabs_end = PTR_ADD (stabp, stab_size);
printf (_("Contents of %s section:\n\n"), sanitize_string (stabsect_name));
printf ("Symnum n_type n_othr n_desc n_value n_strx String\n");
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 - STABSIZE; stabp += STABSIZE, i++)
+ for (i = -1; (size_t) (stabs_end - stabp) >= STABSIZE; stabp += STABSIZE, i++)
{
const char *name;
unsigned long strx;
&& (section->name[len] == 0
|| (section->name[len] == '.' && ISDIGIT (section->name[len + 1]))))
{
+ asection *s;
if (strtab == NULL)
- strtab = read_section_stabs (abfd, sought->string_section_name,
- &stabstr_size, NULL);
+ {
+ s = read_section (abfd, sought->string_section_name, &strtab);
+ if (s != NULL)
+ stabstr_size = bfd_section_size (s);
+ }
if (strtab)
{
- stabs = read_section_stabs (abfd, section->name, &stab_size, NULL);
- if (stabs)
- print_section_stabs (abfd, section->name, &sought->string_offset);
+ s = read_section (abfd, section->name, &stabs);
+ if (s != NULL)
+ {
+ stab_size = bfd_section_size (s);
+ print_section_stabs (abfd, section->name, &sought->string_offset);
+ free (stabs);
+ }
}
}
}
static void
dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name)
{
+ asection *sec;
ctf_archive_t *ctfa = NULL;
- bfd_byte *ctfdata = NULL;
- bfd_size_type ctfsize;
+ bfd_byte *ctfdata;
ctf_sect_t ctfsect;
ctf_dict_t *parent;
ctf_dict_t *fp;
size_t member = 0;
int err;
+ if (sect_name == NULL)
+ sect_name = ".ctf";
- if ((ctfdata = read_section_stabs (abfd, sect_name, &ctfsize, NULL)) == NULL)
- bfd_fatal (bfd_get_filename (abfd));
+ sec = read_section (abfd, sect_name, &ctfdata);
+ if (sec == NULL)
+ {
+ my_bfd_nonfatal (bfd_get_filename (abfd));
+ return;
+ }
/* Load the CTF file and dump it. Preload the parent dict, since it will
need to be imported into every child in turn. */
- ctfsect = make_ctfsect (sect_name, ctfdata, ctfsize);
+ ctfsect = make_ctfsect (sect_name, ctfdata, bfd_section_size (sec));
if ((ctfa = ctf_bfdopen_ctfsect (abfd, &ctfsect, &err)) == NULL)
{
dump_ctf_errs (NULL);
non_fatal (_("CTF open failure: %s"), ctf_errmsg (err));
- bfd_fatal (bfd_get_filename (abfd));
+ my_bfd_nonfatal (bfd_get_filename (abfd));
+ free (ctfdata);
+ return;
}
if ((parent = ctf_dict_open (ctfa, parent_name, &err)) == NULL)
{
dump_ctf_errs (NULL);
non_fatal (_("CTF open failure: %s"), ctf_errmsg (err));
- bfd_fatal (bfd_get_filename (abfd));
+ my_bfd_nonfatal (bfd_get_filename (abfd));
+ ctf_close (ctfa);
+ free (ctfdata);
+ return;
}
printf (_("Contents of CTF section %s:\n"), sanitize_string (sect_name));
{
dump_ctf_errs (NULL);
non_fatal (_("CTF archive member open failure: %s"), ctf_errmsg (err));
- bfd_fatal (bfd_get_filename (abfd));
+ my_bfd_nonfatal (bfd_get_filename (abfd));
}
ctf_dict_close (parent);
ctf_close (ctfa);
const char *parent_name ATTRIBUTE_UNUSED) {}
#endif
+static void
+dump_section_sframe (bfd *abfd ATTRIBUTE_UNUSED,
+ const char * sect_name)
+{
+ asection *sec;
+ sframe_decoder_ctx *sfd_ctx = NULL;
+ bfd_size_type sf_size;
+ bfd_byte *sframe_data;
+ bfd_vma sf_vma;
+ int err = 0;
+
+ if (sect_name == NULL)
+ sect_name = ".sframe";
+
+ sec = read_section (abfd, sect_name, &sframe_data);
+ if (sec == NULL)
+ {
+ my_bfd_nonfatal (bfd_get_filename (abfd));
+ return;
+ }
+ sf_size = bfd_section_size (sec);
+ sf_vma = bfd_section_vma (sec);
+
+ /* Decode the contents of the section. */
+ sfd_ctx = sframe_decode ((const char*)sframe_data, sf_size, &err);
+ if (!sfd_ctx)
+ {
+ my_bfd_nonfatal (bfd_get_filename (abfd));
+ free (sframe_data);
+ return;
+ }
+
+ printf (_("Contents of the SFrame section %s:"),
+ sanitize_string (sect_name));
+ /* Dump the contents as text. */
+ dump_sframe (sfd_ctx, sf_vma);
+
+ sframe_decoder_free (&sfd_ctx);
+ free (sframe_data);
+}
+
\f
static void
dump_bfd_private_header (bfd *abfd)
e = strchr (b, ',');
if (e)
- *e = 0;
+ *e = 0;
for (opt = (*desc)->options; opt->name; opt++)
- if (strcmp (opt->name, b) == 0)
- {
- opt->selected = true;
- break;
- }
+ if (strcmp (opt->name, b) == 0)
+ {
+ opt->selected = true;
+ break;
+ }
if (opt->name == NULL)
- non_fatal (_("target specific dump '%s' not supported"), b);
+ non_fatal (_("target specific dump '%s' not supported"), b);
if (e)
- {
- *e = ',';
- b = e + 1;
- }
+ {
+ *e = ',';
+ b = e + 1;
+ }
}
while (e != NULL);
int count;
int width;
- if (! process_section_p (section))
- return;
-
- if ((section->flags & SEC_HAS_CONTENTS) == 0)
+ if (only_list == NULL)
+ {
+ if ((section->flags & SEC_HAS_CONTENTS) == 0)
+ return;
+ }
+ else if (!process_section_p (section))
return;
if ((datasize = bfd_section_size (section)) == 0)
free (alloc);
}
}
+ else if (unicode_display != unicode_default
+ && name != NULL && *name != '\0')
+ {
+ const char * sanitized_name;
+
+ /* If we want to sanitize the name, we do it here, and
+ temporarily clobber it while calling bfd_print_symbol.
+ FIXME: This is a gross hack. */
+ sanitized_name = sanitize_string (name);
+ if (sanitized_name != name)
+ (*current)->name = sanitized_name;
+ else
+ sanitized_name = NULL;
+ bfd_print_symbol (cur_bfd, stdout, *current,
+ bfd_print_symbol_all);
+ if (sanitized_name != NULL)
+ (*current)->name = name;
+ }
else
bfd_print_symbol (cur_bfd, stdout, *current,
bfd_print_symbol_all);
bfd_sprintf_vma (abfd, buf, (bfd_vma) -1);
width = strlen (buf) - 7;
}
- printf ("OFFSET %*s TYPE %*s VALUE \n", width, "", 12, "");
+ printf ("OFFSET %*s TYPE %*s VALUE\n", width, "", 12, "");
}
last_filename = NULL;
if (with_line_numbers
&& sec != NULL
&& bfd_find_nearest_line_discriminator (abfd, sec, syms, q->address,
- &filename, &functionname,
- &linenumber, &discriminator))
+ &filename, &functionname,
+ &linenumber, &discriminator))
{
if (functionname != NULL
&& (last_functionname == NULL
|| (filename != NULL
&& last_filename != NULL
&& filename_cmp (filename, last_filename) != 0)
- || (discriminator != last_discriminator)))
+ || (discriminator != last_discriminator)))
{
- if (discriminator > 0)
- printf ("%s:%u\n", filename == NULL ? "???" :
+ if (discriminator > 0)
+ printf ("%s:%u\n", filename == NULL ? "???" :
sanitize_string (filename), linenumber);
- else
- printf ("%s:%u (discriminator %u)\n",
+ else
+ printf ("%s:%u (discriminator %u)\n",
filename == NULL ? "???" : sanitize_string (filename),
- linenumber, discriminator);
+ linenumber, discriminator);
last_line = linenumber;
last_discriminator = discriminator;
if (last_filename != NULL)
asection *section,
void *dummy ATTRIBUTE_UNUSED)
{
- arelent **relpp = NULL;
+ arelent **relpp;
long relcount;
long relsize;
}
if (relsize < 0)
- relcount = relsize;
+ {
+ relpp = NULL;
+ relcount = relsize;
+ }
else
{
relpp = (arelent **) xmalloc (relsize);
printf ("\n");
non_fatal (_("failed to read relocs in: %s"),
sanitize_string (bfd_get_filename (abfd)));
- bfd_fatal (_("error message was"));
+ my_bfd_nonfatal (_("error message was"));
}
else if (relcount == 0)
printf (" (none)\n\n");
long relcount;
relsize = bfd_get_dynamic_reloc_upper_bound (abfd);
- if (relsize < 0)
- bfd_fatal (bfd_get_filename (abfd));
printf ("DYNAMIC RELOCATION RECORDS");
if (relsize == 0)
- printf (" (none)\n\n");
+ {
+ printf (" (none)\n\n");
+ return;
+ }
+
+ if (relsize < 0)
+ {
+ relpp = NULL;
+ relcount = relsize;
+ }
else
{
relpp = (arelent **) xmalloc (relsize);
relcount = bfd_canonicalize_dynamic_reloc (abfd, relpp, dynsyms);
+ }
- if (relcount < 0)
- bfd_fatal (bfd_get_filename (abfd));
- else if (relcount == 0)
- printf (" (none)\n\n");
- else
- {
- printf ("\n");
- dump_reloc_set (abfd, NULL, relpp, relcount);
- printf ("\n\n");
- }
- free (relpp);
+ if (relcount < 0)
+ {
+ printf ("\n");
+ non_fatal (_("failed to read relocs in: %s"),
+ sanitize_string (bfd_get_filename (abfd)));
+ my_bfd_nonfatal (_("error message was"));
+ }
+ else if (relcount == 0)
+ printf (" (none)\n\n");
+ else
+ {
+ printf ("\n");
+ dump_reloc_set (abfd, NULL, relpp, relcount);
+ printf ("\n\n");
}
+ free (relpp);
}
/* Creates a table of paths, to search for source files. */
return (((vma & ((mask << 1) - 1)) ^ mask) - mask);
}
+static bool
+might_need_separate_debug_info (bool is_mainfile)
+{
+ /* We do not follow links from debug info files. */
+ if (! is_mainfile)
+ return false;
+
+ /* Since do_follow_links might be enabled by default, only treat it as an
+ indication that separate files should be loaded if setting it was a
+ deliberate user action. */
+ if (DEFAULT_FOR_FOLLOW_LINKS == 0 && do_follow_links)
+ return true;
+
+ if (process_links || dump_symtab || dump_debugging
+ || dump_dwarf_section_info || with_source_code)
+ return true;
+
+ return false;
+}
+
/* Dump selected contents of ABFD. */
static void
else
byte_get = NULL;
- /* Load any separate debug information files.
- We do this now and without checking do_follow_links because separate
- debug info files may contain symbol tables that we will need when
- displaying information about the main file. Any memory allocated by
- load_separate_debug_files will be released when we call
- free_debug_memory below.
-
- The test on is_mainfile is there because the chain of separate debug
- info files is a global variable shared by all invocations of dump_bfd. */
- if (is_mainfile)
+ /* Load any separate debug information files. */
+ if (byte_get != NULL && might_need_separate_debug_info (is_mainfile))
{
load_separate_debug_files (abfd, bfd_get_filename (abfd));
bfd_map_over_sections (abfd, adjust_addresses, &has_reloc);
}
- if (! is_mainfile && ! process_links)
- return;
-
- if (! dump_debugging_tags && ! suppress_bfd_header)
- printf (_("\n%s: file format %s\n"),
- sanitize_string (bfd_get_filename (abfd)),
- abfd->xvec->name);
- if (dump_ar_hdrs)
- print_arelt_descr (stdout, abfd, true, false);
- if (dump_file_header)
- dump_bfd_header (abfd);
- if (dump_private_headers)
- dump_bfd_private_header (abfd);
- if (dump_private_options != NULL)
- dump_target_specific (abfd);
- if (! dump_debugging_tags && ! suppress_bfd_header)
- putchar ('\n');
+ if (is_mainfile || process_links)
+ {
+ if (! dump_debugging_tags && ! suppress_bfd_header)
+ printf (_("\n%s: file format %s\n"),
+ sanitize_string (bfd_get_filename (abfd)),
+ abfd->xvec->name);
+ if (dump_ar_hdrs)
+ print_arelt_descr (stdout, abfd, true, false);
+ if (dump_file_header)
+ dump_bfd_header (abfd);
+ if (dump_private_headers)
+ dump_bfd_private_header (abfd);
+ if (dump_private_options != NULL)
+ dump_target_specific (abfd);
+ if (! dump_debugging_tags && ! suppress_bfd_header)
+ putchar ('\n');
+ }
if (dump_symtab
|| dump_reloc_info
{
asymbol ** extra_syms;
long old_symcount = symcount;
-
+
extra_syms = slurp_symtab (i->handle);
if (extra_syms)
}
}
- if (dump_section_headers)
- dump_headers (abfd);
+ if (is_mainfile || process_links)
+ {
+ if (dump_section_headers)
+ dump_headers (abfd);
- if (dump_dynamic_symtab || dump_dynamic_reloc_info
- || (disassemble && bfd_get_dynamic_symtab_upper_bound (abfd) > 0))
- dynsyms = slurp_dynamic_symtab (abfd);
+ if (dump_dynamic_symtab || dump_dynamic_reloc_info
+ || (disassemble && bfd_get_dynamic_symtab_upper_bound (abfd) > 0))
+ dynsyms = slurp_dynamic_symtab (abfd);
- if (disassemble)
- {
- synthcount = bfd_get_synthetic_symtab (abfd, symcount, syms,
- dynsymcount, dynsyms, &synthsyms);
- if (synthcount < 0)
- synthcount = 0;
- }
+ if (disassemble)
+ {
+ synthcount = bfd_get_synthetic_symtab (abfd, symcount, syms,
+ dynsymcount, dynsyms,
+ &synthsyms);
+ if (synthcount < 0)
+ synthcount = 0;
+ }
- if (dump_symtab)
- dump_symbols (abfd, false);
- if (dump_dynamic_symtab)
- dump_symbols (abfd, true);
+ if (dump_symtab)
+ dump_symbols (abfd, false);
+ if (dump_dynamic_symtab)
+ dump_symbols (abfd, true);
+ }
if (dump_dwarf_section_info)
- dump_dwarf (abfd);
- if (dump_ctf_section_info)
- dump_ctf (abfd, dump_ctf_section_name, dump_ctf_parent_name);
- if (dump_stab_section_info)
- dump_stabs (abfd);
- if (dump_reloc_info && ! disassemble)
- dump_relocs (abfd);
- if (dump_dynamic_reloc_info && ! disassemble)
- dump_dynamic_relocs (abfd);
- if (dump_section_contents)
- dump_data (abfd);
- if (disassemble)
- disassemble_data (abfd);
+ dump_dwarf (abfd, is_mainfile);
+ if (is_mainfile || process_links)
+ {
+ if (dump_ctf_section_info)
+ dump_ctf (abfd, dump_ctf_section_name, dump_ctf_parent_name);
+ if (dump_sframe_section_info)
+ dump_section_sframe (abfd, dump_sframe_section_name);
+ if (dump_stab_section_info)
+ dump_stabs (abfd);
+ if (dump_reloc_info && ! disassemble)
+ dump_relocs (abfd);
+ if (dump_dynamic_reloc_info && ! disassemble)
+ dump_dynamic_relocs (abfd);
+ if (dump_section_contents)
+ dump_data (abfd);
+ if (disassemble)
+ disassemble_data (abfd);
+ }
if (dump_debugging)
{
bfd_get_filename (abfd));
exit_status = 1;
}
-
- free (dhandle);
}
/* PR 6483: If there was no STABS debug info in the file, try
DWARF instead. */
else if (! dump_dwarf_section_info)
{
dwarf_select_sections_all ();
- dump_dwarf (abfd);
+ dump_dwarf (abfd, is_mainfile);
}
}
if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
{
- nonfatal (bfd_get_filename (abfd));
+ my_bfd_nonfatal (bfd_get_filename (abfd));
list_matching_formats (matching);
- free (matching);
return;
}
if (bfd_get_error () != bfd_error_file_not_recognized)
{
- nonfatal (bfd_get_filename (abfd));
+ my_bfd_nonfatal (bfd_get_filename (abfd));
return;
}
return;
}
- nonfatal (bfd_get_filename (abfd));
+ my_bfd_nonfatal (bfd_get_filename (abfd));
if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
- {
- list_matching_formats (matching);
- free (matching);
- }
+ list_matching_formats (matching);
}
static void
bfd *last_arfile = NULL;
if (level == 0)
- printf (_("In archive %s:\n"), sanitize_string (bfd_get_filename (file)));
+ printf (_("In archive %s:\n"), sanitize_string (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"));
+ non_fatal (_("Archive nesting is too deep"));
+ exit_status = 1;
return;
}
else
- printf (_("In nested archive %s:\n"),
+ printf (_("In nested archive %s:\n"),
sanitize_string (bfd_get_filename (file)));
for (;;)
if (arfile == NULL)
{
if (bfd_get_error () != bfd_error_no_more_archived_files)
- nonfatal (bfd_get_filename (file));
+ my_bfd_nonfatal (bfd_get_filename (file));
break;
}
file = bfd_openr (filename, target);
if (file == NULL)
{
- nonfatal (filename);
+ my_bfd_nonfatal (filename);
return;
}
xmalloc_set_program_name (program_name);
bfd_set_error_program_name (program_name);
- START_PROGRESS (program_name, 0);
-
expandargv (&argc, &argv);
if (bfd_init () != BFD_INIT_MAGIC)
set_default_bfd_target ();
while ((c = getopt_long (argc, argv,
- "CDE:FGHI:LM:P:RSTVW::ab:defghij:lm:prstvwxz",
+ "CDE:FGHI:LM:P:RSTU:VW::ab:defghij:lm:prstvwxz",
long_options, (int *) 0))
!= EOF)
{
else if (streq (optarg, "off"))
visualize_jumps = false;
else
- nonfatal (_("unrecognized argument to --visualize-option"));
+ {
+ non_fatal (_("unrecognized argument to --visualize-option"));
+ usage (stderr, 1);
+ }
+ }
+ break;
+ case OPTION_DISASSEMBLER_COLOR:
+ if (streq (optarg, "off"))
+ disassembler_color = off;
+ else if (streq (optarg, "terminal"))
+ disassembler_color = on_if_terminal_output;
+ else if (streq (optarg, "color")
+ || streq (optarg, "colour")
+ || streq (optarg, "on"))
+ disassembler_color = on;
+ else if (streq (optarg, "extended")
+ || streq (optarg, "extended-color")
+ || streq (optarg, "extended-colour"))
+ disassembler_color = extended;
+ else
+ {
+ non_fatal (_("unrecognized argument to --disassembler-color"));
+ usage (stderr, 1);
}
break;
case 'E':
endian = BFD_ENDIAN_LITTLE;
else
{
- nonfatal (_("unrecognized -E option"));
+ non_fatal (_("unrecognized -E option"));
usage (stderr, 1);
}
break;
else
{
non_fatal (_("unrecognized --endian type `%s'"), optarg);
- exit_status = 1;
usage (stderr, 1);
}
break;
do_follow_links = true;
break;
case 'W':
- dump_dwarf_section_info = true;
seenflag = true;
if (optarg)
- dwarf_select_sections_by_letters (optarg);
+ {
+ if (dwarf_select_sections_by_letters (optarg))
+ dump_dwarf_section_info = true;
+ }
else
- dwarf_select_sections_all ();
+ {
+ dump_dwarf_section_info = true;
+ dwarf_select_sections_all ();
+ }
break;
case OPTION_DWARF:
- dump_dwarf_section_info = true;
seenflag = true;
if (optarg)
- dwarf_select_sections_by_names (optarg);
+ {
+ if (dwarf_select_sections_by_names (optarg))
+ dump_dwarf_section_info = true;
+ }
else
- dwarf_select_sections_all ();
+ {
+ dwarf_select_sections_all ();
+ dump_dwarf_section_info = true;
+ }
break;
case OPTION_DWARF_DEPTH:
{
#ifdef ENABLE_LIBCTF
case OPTION_CTF:
dump_ctf_section_info = true;
- dump_ctf_section_name = xstrdup (optarg);
+ if (optarg)
+ dump_ctf_section_name = xstrdup (optarg);
seenflag = true;
break;
case OPTION_CTF_PARENT:
dump_ctf_parent_name = xstrdup (optarg);
break;
#endif
+ case OPTION_SFRAME:
+ dump_sframe_section_info = true;
+ if (optarg)
+ dump_sframe_section_name = xstrdup (optarg);
+ seenflag = true;
+ break;
case 'G':
dump_stab_section_info = true;
seenflag = true;
seenflag = true;
break;
+ case 'U':
+ if (streq (optarg, "default") || streq (optarg, "d"))
+ unicode_display = unicode_default;
+ else if (streq (optarg, "locale") || streq (optarg, "l"))
+ unicode_display = unicode_locale;
+ else if (streq (optarg, "escape") || streq (optarg, "e"))
+ unicode_display = unicode_escape;
+ else if (streq (optarg, "invalid") || streq (optarg, "i"))
+ unicode_display = unicode_invalid;
+ else if (streq (optarg, "hex") || streq (optarg, "x"))
+ unicode_display = unicode_hex;
+ else if (streq (optarg, "highlight") || streq (optarg, "h"))
+ unicode_display = unicode_highlight;
+ else
+ fatal (_("invalid argument to -U/--unicode: %s"), optarg);
+ break;
+
case 'H':
usage (stdout, 0);
/* No need to set seenflag or to break - usage() does not return. */
}
}
+ if (disassembler_color == on_if_terminal_output)
+ disassembler_color = isatty (1) ? on : off;
+
if (show_version)
print_version ("objdump");
if (!seenflag)
usage (stderr, 2);
+ dump_any_debugging = (dump_debugging
+ || dump_dwarf_section_info
+ || process_links
+ || with_source_code);
+
if (formats_info)
exit_status = display_info ();
else
free (dump_ctf_parent_name);
free ((void *) source_comment);
- END_PROGRESS (program_name);
-
return exit_status;
}