#include "bucomm.h"
#include "elfcomm.h"
#include "dwarf.h"
+#include "ctf-api.h"
#include "getopt.h"
#include "safe-ctype.h"
#include "dis-asm.h"
static int show_raw_insn; /* --show-raw-insn */
static int dump_dwarf_section_info; /* --dwarf */
static int dump_stab_section_info; /* --stabs */
+static int dump_ctf_section_info; /* --ctf */
+static char *dump_ctf_section_name;
+static char *dump_ctf_parent_name; /* --ctf-parent */
static int do_demangle; /* -C, --demangle */
static bfd_boolean disassemble; /* -d */
static bfd_boolean disassemble_all; /* -D */
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\
=gdb_index,=trace_info,=trace_abbrev,=trace_aranges,\n\
=addr,=cu_index,=links,=follow-links]\n\
Display DWARF info in the file\n\
+ --ctf=SECTION Display CTF info from SECTION\n\
-t, --syms Display the contents of the symbol table(s)\n\
-T, --dynamic-syms Display the contents of the dynamic symbol table\n\
-r, --reloc Display the relocation entries in the file\n\
--dwarf-start=N Display DIEs starting with N, at the same depth\n\
or deeper\n\
--dwarf-check Make additional dwarf internal consistency checks.\
- \n\n"));
+ \n\
+ --ctf-parent=SECTION Use SECTION as the CTF parent\n\n"));
list_supported_targets (program_name, stream);
list_supported_architectures (program_name, stream);
OPTION_DWARF_START,
OPTION_RECURSE_LIMIT,
OPTION_NO_RECURSE_LIMIT,
- OPTION_INLINES
+ OPTION_INLINES,
+ OPTION_SOURCE_COMMENT,
+ OPTION_CTF,
+ OPTION_CTF_PARENT
};
static struct option long_options[]=
{"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},
+ {"ctf", required_argument, NULL, OPTION_CTF},
+ {"ctf-parent", required_argument, NULL, OPTION_CTF_PARENT},
{"stabs", no_argument, NULL, 'G'},
{"start-address", required_argument, NULL, OPTION_START_ADDRESS},
{"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS},
static const char *
sanitize_string (const char * in)
{
- static char * buffer = NULL;
- static unsigned int buffer_len = 0;
- const char * original = in;
- char * out;
+ static char * buffer = NULL;
+ static size_t buffer_len = 0;
+ const char * original = in;
+ char * out;
/* Paranoia. */
if (in == NULL)
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');
}
inf->stream = &sfile;
inf->bytes_per_line = 0;
inf->bytes_per_chunk = 0;
- inf->flags = disassemble_all ? DISASSEMBLE_DATA : 0;
+ inf->flags = ((disassemble_all ? DISASSEMBLE_DATA : 0)
+ | (wide_output ? WIDE_OUTPUT : 0));
if (machine)
inf->flags |= USER_SPECIFIED_MACHINE_TYPE;
disassembling code of course, and when -D is in effect. */
inf->stop_vma = section->vma + stop_offset;
+ inf->stop_offset = stop_offset;
octets = (*disassemble_fn) (section->vma + addr_offset, inf);
inf->stop_vma = 0;
bfd *abfd = (bfd *) file;
bfd_byte *contents;
bfd_size_type amt;
+ size_t alloced;
if (section->start != NULL)
{
section->address = bfd_get_section_vma (abfd, sec);
section->user_data = sec;
section->size = bfd_get_section_size (sec);
- amt = section->size + 1;
- if (amt == 0)
+ /* PR 24360: On 32-bit hosts sizeof (size_t) < sizeof (bfd_size_type). */
+ alloced = amt = section->size + 1;
+ if (alloced != amt || alloced == 0)
{
section->start = NULL;
free_debug_section (debug);
(unsigned long long) section->size);
return FALSE;
}
- section->start = contents = malloc (amt);
+ section->start = contents = malloc (alloced);
if (section->start == NULL
|| !bfd_get_full_section_contents (abfd, sec, &contents))
{
/* 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))
it. Return NULL on failure. */
static bfd_byte *
-read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr)
+read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr,
+ bfd_size_type *entsize_ptr)
{
asection *stabsect;
bfd_byte *contents;
}
*size_ptr = bfd_section_size (abfd, stabsect);
+ if (entsize_ptr)
+ *entsize_ptr = stabsect->entsize;
return contents;
}
{
if (strtab == NULL)
strtab = read_section_stabs (abfd, sought->string_section_name,
- &stabstr_size);
+ &stabstr_size, NULL);
if (strtab)
{
- stabs = read_section_stabs (abfd, section->name, &stab_size);
+ stabs = read_section_stabs (abfd, section->name, &stab_size, NULL);
if (stabs)
print_section_stabs (abfd, section->name, &sought->string_offset);
}
bfd_printf_vma (abfd, abfd->start_address);
printf ("\n");
}
+\f
+
+/* Formatting callback function passed to ctf_dump. Returns either the pointer
+ it is passed, or a pointer to newly-allocated storage, in which case
+ dump_ctf() will free it when it no longer needs it. */
+
+static char *
+dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED,
+ char *s, void *arg)
+{
+ const char *blanks = arg;
+ char *new_s;
+
+ if (asprintf (&new_s, "%s%s", blanks, s) < 0)
+ return s;
+ return new_s;
+}
+
+/* Make a ctfsect suitable for ctf_bfdopen_ctfsect(). */
+static ctf_sect_t
+make_ctfsect (const char *name, bfd_byte *data,
+ bfd_size_type size)
+{
+ ctf_sect_t ctfsect;
+
+ ctfsect.cts_name = name;
+ ctfsect.cts_entsize = 1;
+ ctfsect.cts_size = size;
+ ctfsect.cts_data = data;
+
+ return ctfsect;
+}
+
+/* Dump one CTF archive member. */
+
+static int
+dump_ctf_archive_member (ctf_file_t *ctf, const char *name, void *arg)
+{
+ ctf_file_t *parent = (ctf_file_t *) arg;
+ const char *things[] = {"Labels", "Data objects", "Function objects",
+ "Variables", "Types", "Strings", ""};
+ const char **thing;
+ size_t i;
+
+ /* Only print out the name of non-default-named archive members.
+ The name .ctf appears everywhere, even for things that aren't
+ really archives, so printing it out is liable to be confusing. */
+ if (strcmp (name, ".ctf") != 0)
+ printf (_("\nCTF archive member: %s:\n"), sanitize_string (name));
+
+ ctf_import (ctf, parent);
+ for (i = 1, thing = things; *thing[0]; thing++, i++)
+ {
+ ctf_dump_state_t *s = NULL;
+ char *item;
+
+ printf ("\n %s:\n", *thing);
+ while ((item = ctf_dump (ctf, &s, i, dump_ctf_indent_lines,
+ (void *) " ")) != NULL)
+ {
+ printf ("%s\n", item);
+ free (item);
+ }
+
+ if (ctf_errno (ctf))
+ {
+ non_fatal (_("Iteration failed: %s, %s\n"), *thing,
+ ctf_errmsg (ctf_errno (ctf)));
+ break;
+ }
+ }
+ return 0;
+}
+
+/* Dump the CTF debugging information. */
+
+static void
+dump_ctf (bfd *abfd, const char *sect_name, const char *parent_name)
+{
+ ctf_archive_t *ctfa, *parenta = NULL;
+ bfd_byte *ctfdata, *parentdata = NULL;
+ bfd_size_type ctfsize, parentsize;
+ ctf_sect_t ctfsect;
+ ctf_file_t *parent = NULL;
+ int err;
+
+ if ((ctfdata = read_section_stabs (abfd, sect_name, &ctfsize, NULL)) == NULL)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ if (parent_name
+ && (parentdata = read_section_stabs (abfd, parent_name, &parentsize,
+ NULL)) == NULL)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ /* Load the CTF file and dump it. */
+
+ ctfsect = make_ctfsect (sect_name, ctfdata, ctfsize);
+ if ((ctfa = ctf_bfdopen_ctfsect (abfd, &ctfsect, &err)) == NULL)
+ {
+ non_fatal (_("CTF open failure: %s\n"), ctf_errmsg (err));
+ bfd_fatal (bfd_get_filename (abfd));
+ }
+
+ if (parentdata)
+ {
+ ctfsect = make_ctfsect (parent_name, parentdata, parentsize);
+ if ((parenta = ctf_bfdopen_ctfsect (abfd, &ctfsect, &err)) == NULL)
+ {
+ non_fatal (_("CTF open failure: %s\n"), ctf_errmsg (err));
+ bfd_fatal (bfd_get_filename (abfd));
+ }
+
+ /* Assume that the applicable parent archive member is the default one.
+ (This is what all known implementations are expected to do, if they
+ put CTFs and their parents in archives together.) */
+ if ((parent = ctf_arc_open_by_name (parenta, NULL, &err)) == NULL)
+ {
+ non_fatal (_("CTF open failure: %s\n"), ctf_errmsg (err));
+ bfd_fatal (bfd_get_filename (abfd));
+ }
+ }
+
+ printf (_("Contents of CTF section %s:\n"), sanitize_string (sect_name));
+
+ ctf_archive_iter (ctfa, dump_ctf_archive_member, parent);
+ ctf_file_close (parent);
+ ctf_close (ctfa);
+ ctf_close (parenta);
+ free (parentdata);
+ free (ctfdata);
+}
\f
static void
asection *section,
void *dummy ATTRIBUTE_UNUSED)
{
- arelent **relpp;
+ arelent **relpp = NULL;
long relcount;
long relsize;
}
}
+/* Return the sign-extended form of an ARCH_SIZE sized VMA. */
+
+static bfd_vma
+sign_extend_address (bfd *abfd ATTRIBUTE_UNUSED,
+ bfd_vma vma,
+ unsigned arch_size)
+{
+ bfd_vma mask;
+ mask = (bfd_vma) 1 << (arch_size - 1);
+ return (((vma & ((mask << 1) - 1)) ^ mask) - mask);
+}
+
/* Dump selected contents of ABFD. */
static void
dump_bfd (bfd *abfd, bfd_boolean is_mainfile)
{
+ const struct elf_backend_data * bed;
+
if (bfd_big_endian (abfd))
byte_get = byte_get_big_endian;
else if (bfd_little_endian (abfd))
}
}
+ /* Adjust user-specified start and stop limits for targets that use
+ signed addresses. */
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && (bed = get_elf_backend_data (abfd)) != NULL
+ && bed->sign_extend_vma)
+ {
+ start_address = sign_extend_address (abfd, start_address,
+ bed->s->arch_size);
+ stop_address = sign_extend_address (abfd, stop_address,
+ bed->s->arch_size);
+ }
+
/* 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. */
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)
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;
case OPTION_DWARF_CHECK:
dwarf_check = TRUE;
break;
+ case OPTION_CTF:
+ dump_ctf_section_info = TRUE;
+ dump_ctf_section_name = xstrdup (optarg);
+ seenflag = TRUE;
+ break;
+ case OPTION_CTF_PARENT:
+ dump_ctf_parent_name = xstrdup (optarg);
+ break;
case 'G':
dump_stab_section_info = TRUE;
seenflag = TRUE;
}
free_only_list ();
+ free (dump_ctf_section_name);
+ free (dump_ctf_parent_name);
+ free ((void *) source_comment);
END_PROGRESS (program_name);