#include <ctype.h>
#include "dis-asm.h"
#include "libiberty.h"
+#include "demangle.h"
#include "debug.h"
#include "budbg.h"
static boolean with_source_code; /* -S */
static int show_raw_insn; /* --show-raw-insn */
static int dump_stab_section_info; /* --stabs */
+static int do_demangle; /* -C, --demangle */
static boolean disassemble; /* -d */
static boolean disassemble_all; /* -D */
static int disassemble_zeroes; /* --disassemble-zeroes */
static bfd_vma start_address = (bfd_vma) -1; /* --start-address */
static bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */
static int dump_debugging; /* --debugging */
+static bfd_vma adjust_section_vma = 0; /* --adjust-vma */
/* Extra info to pass to the disassembler address printing function. */
struct objdump_disasm_info {
static void
objdump_print_value PARAMS ((bfd_vma, struct disassemble_info *, boolean));
+static void
+objdump_print_symname PARAMS ((bfd *, struct disassemble_info *, asymbol *));
+
static asymbol *
find_symbol_for_address PARAMS ((bfd *, asection *, bfd_vma, boolean, long *));
int status;
{
fprintf (stream, "\
-Usage: %s [-ahifdDprRtTxsSlw] [-b bfdname] [-m machine] [-j section-name]\n\
+Usage: %s [-ahifCdDprRtTxsSlw] [-b bfdname] [-m machine] [-j section-name]\n\
[--archive-headers] [--target=bfdname] [--debugging] [--disassemble]\n\
[--disassemble-all] [--disassemble-zeroes] [--file-headers]\n\
[--section-headers] [--headers]\n\
[--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n\
[--wide] [--version] [--help] [--private-headers]\n\
[--start-address=addr] [--stop-address=addr]\n\
- [--prefix-addresses] [--show-raw-insn]\n\
- [-EB|-EL] [--endian={big|little}] objfile...\n\
+ [--prefix-addresses] [--[no-]show-raw-insn] [--demangle]\n\
+ [--adjust-vma=offset] [-EB|-EL] [--endian={big|little}] objfile...\n\
at least one option besides -l (--line-numbers) must be given\n");
list_supported_targets (program_name, stream);
if (status == 0)
#define OPTION_ENDIAN (150)
#define OPTION_START_ADDRESS (OPTION_ENDIAN + 1)
#define OPTION_STOP_ADDRESS (OPTION_START_ADDRESS + 1)
+#define OPTION_ADJUST_VMA (OPTION_STOP_ADDRESS + 1)
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'},
{"architecture", required_argument, NULL, 'm'},
{"archive-headers", no_argument, NULL, 'a'},
{"debugging", no_argument, &dump_debugging, 1},
+ {"demangle", no_argument, &do_demangle, 1},
{"disassemble", no_argument, NULL, 'd'},
{"disassemble-all", no_argument, NULL, 'D'},
{"disassemble-zeroes", no_argument, &disassemble_zeroes, 1},
{"help", no_argument, NULL, 'H'},
{"info", no_argument, NULL, 'i'},
{"line-numbers", no_argument, NULL, 'l'},
+ {"no-show-raw-insn", no_argument, &show_raw_insn, -1},
{"prefix-addresses", no_argument, &prefix_addresses, 1},
{"reloc", no_argument, NULL, 'r'},
{"section", required_argument, NULL, 'j'},
(*info->fprintf_func) (info->stream, "%s", p);
}
+/* Print the name of a symbol. */
+
+static void
+objdump_print_symname (abfd, info, sym)
+ bfd *abfd;
+ struct disassemble_info *info;
+ asymbol *sym;
+{
+ char *alloc;
+ const char *name;
+ const char *print;
+
+ alloc = NULL;
+ name = bfd_asymbol_name (sym);
+ if (! do_demangle || name[0] == '\0')
+ print = name;
+ else
+ {
+ /* Demangle the name. */
+ if (bfd_get_symbol_leading_char (abfd) == name[0])
+ ++name;
+
+ alloc = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+ if (alloc == NULL)
+ print = name;
+ else
+ print = alloc;
+ }
+
+ if (info != NULL)
+ (*info->fprintf_func) (info->stream, "%s", print);
+ else
+ printf ("%s", print);
+
+ if (alloc != NULL)
+ free (alloc);
+}
+
/* Locate a symbol given a bfd, a section, and a VMA. If REQUIRE_SEC
is true, then always require the symbol to be in the section. This
returns NULL if there is no suitable symbol. If PLACE is not NULL,
}
else
{
- (*info->fprintf_func) (info->stream, " <%s", sym->name);
+ (*info->fprintf_func) (info->stream, " <");
+ objdump_print_symname (abfd, info, sym);
if (bfd_asymbol_value (sym) > vma)
{
(*info->fprintf_func) (info->stream, "-");
buf[j - i] = '\0';
}
- if (! prefix_addresses || show_raw_insn)
+ if (prefix_addresses
+ ? show_raw_insn > 0
+ : show_raw_insn >= 0)
{
long j;
int k;
if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE)
{
- for (k=bpc-1; k >= 0; k--)
- printf ("%02x", (unsigned) data[j+k]);
+ for (k = bpc - 1; k >= 0; k--)
+ printf ("%02x", (unsigned) data[j + k]);
putchar (' ');
}
else
{
- for (k=0; k < bpc; k++)
- printf ("%02x", (unsigned) data[j+k]);
+ for (k = 0; k < bpc; k++)
+ printf ("%02x", (unsigned) data[j + k]);
putchar (' ');
}
}
- for (; pb < bytes_per_line; ++pb)
- printf (" ");
+ for (; pb < bytes_per_line; pb += bpc)
+ {
+ int k;
+
+ for (k = 0; k < bpc; k++)
+ printf (" ");
+ putchar (' ');
+ }
/* Separate raw data from instruction by extra space. */
if (insns)
printf ("%s", buf);
- if (! prefix_addresses || show_raw_insn)
+ if (prefix_addresses
+ ? show_raw_insn > 0
+ : show_raw_insn >= 0)
{
while (pb < bytes)
{
pb += bytes_per_line;
if (pb > bytes)
pb = bytes;
- for (; j < i + pb; ++j)
+ for (; j < i + pb; j += bpc)
{
- printf ("%02x", (unsigned) data[j]);
- putchar (' ');
+ int k;
+
+ if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE)
+ {
+ for (k = bpc - 1; k >= 0; k--)
+ printf ("%02x", (unsigned) data[j + k]);
+ putchar (' ');
+ }
+ else
+ {
+ for (k = 0; k < bpc; k++)
+ printf ("%02x", (unsigned) data[j + k]);
+ putchar (' ');
+ }
}
}
}
&& (**relppp)->address < (bfd_vma) i + bytes))
{
arelent *q;
- const char *sym_name;
q = **relppp;
printf (": %s\t", q->howto->name);
- if (q->sym_ptr_ptr != NULL
- && *q->sym_ptr_ptr != NULL)
+ if (q->sym_ptr_ptr == NULL || *q->sym_ptr_ptr == NULL)
+ printf ("*unknown*");
+ else
{
+ const char *sym_name;
+
sym_name = bfd_asymbol_name (*q->sym_ptr_ptr);
- if (sym_name == NULL || *sym_name == '\0')
+ if (sym_name != NULL && *sym_name != '\0')
+ objdump_print_symname (aux->abfd, info, *q->sym_ptr_ptr);
+ else
{
asection *sym_sec;
sym_sec = bfd_get_section (*q->sym_ptr_ptr);
- sym_name = bfd_get_section_name (abfd, sym_sec);
+ sym_name = bfd_get_section_name (aux->abfd, sym_sec);
if (sym_name == NULL || *sym_name == '\0')
sym_name = "*unknown*";
+ printf ("%s", sym_name);
}
}
- else
- sym_name = "*unknown*";
-
- printf ("%s", sym_name);
if (q->addend)
{
asymbol *sym;
long place;
- sym = find_symbol_for_address (abfd, section, i, true, &place);
+ sym = find_symbol_for_address (abfd, section, section->vma + i,
+ true, &place);
++place;
while (i < stop)
{
long nextstop;
boolean insns;
- disasm_info.symbol = sym;
+ if (sym != NULL && bfd_asymbol_value (sym) <= section->vma + i)
+ disasm_info.symbol = sym;
+ else
+ disasm_info.symbol = NULL;
printf ("\n");
objdump_print_addr_with_sym (abfd, section, sym,
false);
printf (":\n");
- if (sym == NULL)
+ if (sym != NULL && bfd_asymbol_value (sym) > section->vma + i)
+ nextsym = sym;
+ else if (sym == NULL)
nextsym = NULL;
else
{
nextsym = sorted_syms[place];
}
- if (nextsym == NULL)
+ if (sym != NULL && bfd_asymbol_value (sym) > section->vma + i)
+ {
+ nextstop = bfd_asymbol_value (sym) - section->vma;
+ if (nextstop > stop)
+ nextstop = stop;
+ }
+ else if (nextsym == NULL)
nextstop = stop;
else
{
disassembling them. */
if (disassemble_all
|| sym == NULL
+ || bfd_asymbol_value (sym) > section->vma + i
|| ((sym->flags & BSF_OBJECT) == 0
&& (strstr (bfd_asymbol_name (sym), "gnu_compiled")
== NULL)
return;
}
+ /* If we are adjusting section VMA's, change them all now. Changing
+ the BFD information is a hack. However, we must do it, or
+ bfd_find_nearest_line will not do the right thing. */
+ if (adjust_section_vma != 0)
+ {
+ asection *s;
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ s->vma += adjust_section_vma;
+ s->lma += adjust_section_vma;
+ }
+ }
+
printf ("\n%s: file format %s\n", bfd_get_filename (abfd),
abfd->xvec->name);
if (dump_ar_hdrs)
{
if (*current)
{
- bfd *cur_bfd = bfd_asymbol_bfd(*current);
- if (cur_bfd)
+ bfd *cur_bfd = bfd_asymbol_bfd (*current);
+
+ if (cur_bfd != NULL)
{
- bfd_print_symbol (cur_bfd,
- stdout,
- *current, bfd_print_symbol_all);
+ const char *name;
+ char *alloc;
+
+ name = bfd_asymbol_name (*current);
+ alloc = NULL;
+ if (do_demangle && name != NULL && *name != '\0')
+ {
+ const char *n;
+
+ /* If we want to demangle the name, we demangle it
+ here, and temporarily clobber it while calling
+ bfd_print_symbol. FIXME: This is a gross hack. */
+
+ n = name;
+ if (bfd_get_symbol_leading_char (cur_bfd) == *n)
+ ++n;
+ alloc = cplus_demangle (n, DMGL_ANSI | DMGL_PARAMS);
+ if (alloc != NULL)
+ (*current)->name = alloc;
+ else
+ (*current)->name = n;
+ }
+
+ bfd_print_symbol (cur_bfd, stdout, *current,
+ bfd_print_symbol_all);
+
+ (*current)->name = name;
+ if (alloc != NULL)
+ free (alloc);
+
printf ("\n");
}
}
if (sym_name)
{
printf_vma (q->address);
- printf (" %-16s %s",
- q->howto->name,
- sym_name);
+ printf (" %-16s ", q->howto->name);
+ objdump_print_symname (abfd, (struct disassemble_info *) NULL,
+ *q->sym_ptr_ptr);
}
else
{
START_PROGRESS (program_name, 0);
bfd_init ();
+ set_default_bfd_target ();
- while ((c = getopt_long (argc, argv, "pib:m:VdDlfahrRtTxsSj:wE:",
+ while ((c = getopt_long (argc, argv, "pib:m:VCdDlfahrRtTxsSj:wE:",
long_options, (int *) 0))
!= EOF)
{
case 'T':
dump_dynamic_symtab = 1;
break;
+ case 'C':
+ do_demangle = 1;
+ break;
case 'd':
disassemble = true;
break;
case 'w':
wide_output = 1;
break;
+ case OPTION_ADJUST_VMA:
+ adjust_section_vma = parse_vma (optarg, "--adjust-vma");
+ break;
case OPTION_START_ADDRESS:
start_address = parse_vma (optarg, "--start-address");
break;