static size_t prefix_length;
static bfd_boolean unwind_inlines; /* --inlines. */
static const char * disasm_sym; /* Disassembly start symbol. */
+static const char * source_comment; /* --source_comment. */
static int demangle_flags = DMGL_ANSI | DMGL_PARAMS;
static bfd_byte *strtab;
static bfd_size_type stabstr_size;
-static bfd_boolean is_relocatable = FALSE;
-
/* Handlers for -P/--private. */
static const struct objdump_private_desc * const objdump_private_vectors[] =
{
-D, --disassemble-all Display assembler contents of all sections\n\
--disassemble=<sym> Display assembler contents from <sym>\n\
-S, --source Intermix source code with disassembly\n\
+ --source-comment[=<txt>] Prefix lines of source code with <txt>\n\
-s, --full-contents Display the full contents of all sections requested\n\
-g, --debugging Display debug information in object file\n\
-e, --debugging-tags Display debug information using ctags style\n\
OPTION_RECURSE_LIMIT,
OPTION_NO_RECURSE_LIMIT,
OPTION_INLINES,
+ OPTION_SOURCE_COMMENT,
OPTION_CTF,
OPTION_CTF_PARENT
};
{"section-headers", no_argument, NULL, 'h'},
{"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},
bfd_fatal (_("error message was"));
}
if (storage)
- sy = (asymbol **) xmalloc (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);
+ }
symcount = bfd_canonicalize_symtab (abfd, sy);
if (symcount < 0)
if (linenum >= p->maxline)
return;
l = p->linemap [linenum];
- /* Test fwrite return value to quiet glibc warning. */
+ if (source_comment != NULL && strlen (l) > 0)
+ printf ("%s", source_comment);
len = strcspn (l, "\n\r");
+ /* Test fwrite return value to quiet glibc warning. */
if (len == 0 || fwrite (l, len, 1, stdout) == 1)
putchar ('\n');
}
#define DEFAULT_SKIP_ZEROES_AT_END 3
+static int
+null_print (const void * stream ATTRIBUTE_UNUSED, const char * format ATTRIBUTE_UNUSED, ...)
+{
+ return 1;
+}
+
/* Disassemble some data in memory between given values. */
static void
{
bfd_vma z;
bfd_boolean need_nl = FALSE;
- int previous_octets;
- /* Remember the length of the previous instruction. */
- previous_octets = octets;
octets = 0;
/* Make sure we don't use relocs from previous instructions. */
&& *relppp < relppend)
{
bfd_signed_vma distance_to_rel;
+ int insn_size = 0;
+ int max_reloc_offset
+ = aux->abfd->arch_info->max_reloc_offset_into_insn;
+
+ distance_to_rel = ((**relppp)->address - rel_offset
+ - addr_offset);
- distance_to_rel = (**relppp)->address
- - (rel_offset + addr_offset);
+ if (distance_to_rel > 0
+ && (max_reloc_offset < 0
+ || distance_to_rel <= max_reloc_offset))
+ {
+ /* This reloc *might* apply to the current insn,
+ starting somewhere inside it. Discover the length
+ of the current insn so that the check below will
+ work. */
+ if (insn_width)
+ insn_size = insn_width;
+ else
+ {
+ /* We find the length by calling the dissassembler
+ function with a dummy print handler. This should
+ work unless the disassembler is not expecting to
+ be called multiple times for the same address.
+
+ This does mean disassembling the instruction
+ 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;
+ insn_size = disassemble_fn (section->vma
+ + addr_offset, inf);
+ inf->fprintf_func = (fprintf_ftype) objdump_sprintf;
+ }
+ }
/* Check to see if the current reloc is associated with
the instruction that we are about to disassemble. */
if (distance_to_rel == 0
- /* FIXME: This is wrong. We are trying to catch
- relocs that are addressed part way through the
- current instruction, as might happen with a packed
- VLIW instruction. Unfortunately we do not know the
- length of the current instruction since we have not
- disassembled it yet. Instead we take a guess based
- upon the length of the previous instruction. The
- proper solution is to have a new target-specific
- disassembler function which just returns the length
- of an instruction at a given address without trying
- to display its disassembly. */
|| (distance_to_rel > 0
- && distance_to_rel < (bfd_signed_vma) (previous_octets/ opb)))
+ && distance_to_rel < insn_size / (int) opb))
{
inf->flags |= INSN_HAS_RELOC;
aux->reloc = **relppp;
/* Ensure any string section has a terminating NUL. */
section->start[section->size] = 0;
- if (is_relocatable && debug_displays [debug].relocate)
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
+ && debug_displays [debug].relocate)
{
long reloc_size;
bfd_boolean ret;
return;
}
- is_relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
-
eh_addr_size = bfd_arch_bits_per_address (abfd) / 8;
switch (bfd_get_arch (abfd))
with_source_code = TRUE;
seenflag = TRUE;
break;
+ case OPTION_SOURCE_COMMENT:
+ disassemble = TRUE;
+ with_source_code = TRUE;
+ seenflag = TRUE;
+ if (optarg)
+ source_comment = xstrdup (sanitize_string (optarg));
+ else
+ source_comment = xstrdup ("# ");
+ break;
case 'g':
dump_debugging = 1;
seenflag = TRUE;
free_only_list ();
free (dump_ctf_section_name);
free (dump_ctf_parent_name);
+ free ((void *) source_comment);
END_PROGRESS (program_name);