X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fobjdump.c;h=6a1f142a0ebc8f354c2999ba3c5d91aa8148554f;hb=229a22cfd2fd3c82a1b57d4af104f361cb0b0a33;hp=ab091c10d4bfcffef991026ab2b9469d2362965c;hpb=39f0547e554df96608dd041d2a7b3c72882fd515;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/objdump.c b/binutils/objdump.c index ab091c10d4..6a1f142a0e 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -56,6 +56,7 @@ #include "bucomm.h" #include "elfcomm.h" #include "dwarf.h" +#include "ctf-api.h" #include "getopt.h" #include "safe-ctype.h" #include "dis-asm.h" @@ -98,6 +99,9 @@ static bfd_boolean with_source_code; /* -S */ 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 */ @@ -119,6 +123,7 @@ static int prefix_strip; /* --prefix-strip */ 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; @@ -188,8 +193,6 @@ static bfd_size_type stab_size; 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[] = { @@ -215,6 +218,7 @@ usage (FILE *stream, int status) -D, --disassemble-all Display assembler contents of all sections\n\ --disassemble= Display assembler contents from \n\ -S, --source Intermix source code with disassembly\n\ + --source-comment[=] Prefix lines of source code with \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\ @@ -225,6 +229,7 @@ usage (FILE *stream, int status) =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\ @@ -259,7 +264,7 @@ usage (FILE *stream, int status) -w, --wide Format output for more than 80 columns\n\ -z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n\ --start-address=ADDR Only process data whose address is >= ADDR\n\ - --stop-address=ADDR Only process data whose address is <= ADDR\n\ + --stop-address=ADDR Only process data whose address is < ADDR\n\ --prefix-addresses Print complete address alongside disassembly\n\ --[no-]show-raw-insn Display hex alongside symbolic disassembly\n\ --insn-width=WIDTH Display WIDTH bytes on a single line for -d\n\ @@ -273,7 +278,8 @@ usage (FILE *stream, int status) --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); @@ -308,7 +314,10 @@ enum option_values 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[]= @@ -348,9 +357,12 @@ 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}, @@ -382,10 +394,10 @@ nonfatal (const char *msg) 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) @@ -520,7 +532,7 @@ static void dump_section_header (bfd *abfd, asection *section, void *data) { char *comma = ""; - unsigned int opb = bfd_octets_per_byte (abfd); + unsigned int opb = bfd_octets_per_byte (abfd, section); int longest_section_name = *((int *) data); /* Ignore linker created section. See elfNN_ia64_object_p in @@ -533,13 +545,13 @@ dump_section_header (bfd *abfd, asection *section, void *data) return; printf ("%3d %-*s %08lx ", section->index, longest_section_name, - sanitize_string (bfd_get_section_name (abfd, section)), - (unsigned long) bfd_section_size (abfd, section) / opb); - bfd_printf_vma (abfd, bfd_get_section_vma (abfd, section)); + sanitize_string (bfd_section_name (section)), + (unsigned long) bfd_section_size (section) / opb); + bfd_printf_vma (abfd, bfd_section_vma (section)); printf (" "); bfd_printf_vma (abfd, section->lma); printf (" %08lx 2**%u", (unsigned long) section->filepos, - bfd_get_section_alignment (abfd, section)); + bfd_section_alignment (section)); if (! wide_output) printf ("\n "); printf (" "); @@ -572,7 +584,10 @@ dump_section_header (bfd *abfd, asection *section, void *data) PF (SEC_COFF_NOREAD, "NOREAD"); } else if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) - PF (SEC_ELF_PURECODE, "PURECODE"); + { + PF (SEC_ELF_OCTETS, "OCTETS"); + PF (SEC_ELF_PURECODE, "PURECODE"); + } PF (SEC_THREAD_LOCAL, "THREAD_LOCAL"); PF (SEC_GROUP, "GROUP"); if (bfd_get_arch (abfd) == bfd_arch_mep) @@ -619,7 +634,8 @@ dump_section_header (bfd *abfd, asection *section, void *data) DATA which contains the string length of the longest section name. */ static void -find_longest_section_name (bfd *abfd, asection *section, void *data) +find_longest_section_name (bfd *abfd ATTRIBUTE_UNUSED, + asection *section, void *data) { int *longest_so_far = (int *) data; const char *name; @@ -633,7 +649,7 @@ find_longest_section_name (bfd *abfd, asection *section, void *data) if (! process_section_p (section)) return; - name = bfd_get_section_name (abfd, section); + name = bfd_section_name (section); len = (int) strlen (name); if (len > *longest_so_far) *longest_so_far = len; @@ -694,7 +710,26 @@ slurp_symtab (bfd *abfd) 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) @@ -964,7 +999,7 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *inf, if ((sym->flags & (BSF_SECTION_SYM | BSF_SYNTHETIC)) == 0) version_string = bfd_get_symbol_version_string (abfd, sym, &hidden); - if (bfd_is_und_section (bfd_get_section (sym))) + if (bfd_is_und_section (bfd_asymbol_section (sym))) hidden = TRUE; name = sanitize_string (name); @@ -1003,8 +1038,8 @@ sym_ok (bfd_boolean want_section, debug info file, whilst the section we want is in a normal file. So the section pointers will be different, but the section names will be the same. */ - if (strcmp (bfd_section_name (abfd, sorted_syms[place]->section), - bfd_section_name (abfd, sec)) != 0) + if (strcmp (bfd_section_name (sorted_syms[place]->section), + bfd_section_name (sec)) != 0) return FALSE; } @@ -1110,9 +1145,9 @@ find_symbol_for_address (bfd_vma vma, Also give the target a chance to reject symbols. */ want_section = (aux->require_sec || ((abfd->flags & HAS_RELOC) != 0 - && vma >= bfd_get_section_vma (abfd, sec) - && vma < (bfd_get_section_vma (abfd, sec) - + bfd_section_size (abfd, sec) / opb))); + && vma >= bfd_section_vma (sec) + && vma < (bfd_section_vma (sec) + + bfd_section_size (sec) / opb))); if (! sym_ok (want_section, abfd, thisplace, sec, inf)) { @@ -1236,8 +1271,8 @@ objdump_print_addr_with_sym (bfd *abfd, asection *sec, asymbol *sym, bfd_vma secaddr; (*inf->fprintf_func) (inf->stream, " <%s", - sanitize_string (bfd_get_section_name (abfd, sec))); - secaddr = bfd_get_section_vma (abfd, sec); + sanitize_string (bfd_section_name (sec))); + secaddr = bfd_section_vma (sec); if (vma < secaddr) { (*inf->fprintf_func) (inf->stream, "-0x"); @@ -1320,7 +1355,7 @@ objdump_print_addr (bfd_vma vma, /* Adjust the vma to the reloc. */ vma += bfd_asymbol_value (sym); - if (bfd_is_und_section (bfd_get_section (sym))) + if (bfd_is_und_section (bfd_asymbol_section (sym))) skip_find = TRUE; } @@ -1567,8 +1602,10 @@ print_line (struct print_file_list *p, unsigned int linenum) 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'); } @@ -1803,6 +1840,12 @@ objdump_sprintf (SFILE *f, const char *format, ...) #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 @@ -1870,10 +1913,7 @@ disassemble_bytes (struct disassemble_info * inf, { 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. */ @@ -1946,7 +1986,8 @@ disassemble_bytes (struct disassemble_info * inf, 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; @@ -1956,26 +1997,46 @@ disassemble_bytes (struct disassemble_info * inf, && *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; @@ -1991,6 +2052,7 @@ disassemble_bytes (struct disassemble_info * inf, 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; @@ -2176,8 +2238,8 @@ disassemble_bytes (struct disassemble_info * inf, { asection *sym_sec; - sym_sec = bfd_get_section (*q->sym_ptr_ptr); - sym_name = bfd_get_section_name (aux->abfd, sym_sec); + sym_sec = bfd_asymbol_section (*q->sym_ptr_ptr); + sym_name = bfd_section_name (sym_sec); if (sym_name == NULL || *sym_name == '\0') sym_name = "*unknown*"; printf ("%s", sanitize_string (sym_name)); @@ -2250,7 +2312,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf) if (! process_section_p (section)) return; - datasize = bfd_get_section_size (section); + datasize = bfd_section_size (section); if (datasize == 0) return; @@ -2480,7 +2542,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf) else { #define is_valid_next_sym(SYM) \ - (strcmp (bfd_section_name (abfd, (SYM)->section), bfd_section_name (abfd, section)) == 0 \ + (strcmp (bfd_section_name ((SYM)->section), bfd_section_name (section)) == 0 \ && (bfd_asymbol_value (SYM) > bfd_asymbol_value (sym)) \ && pinfo->symbol_is_valid (SYM, pinfo)) @@ -2623,7 +2685,7 @@ disassemble_data (bfd *abfd) disasm_info.arch = bfd_get_arch (abfd); disasm_info.mach = bfd_get_mach (abfd); disasm_info.disassembler_options = disassembler_options; - disasm_info.octets_per_byte = bfd_octets_per_byte (abfd); + disasm_info.octets_per_byte = bfd_octets_per_byte (abfd, NULL); disasm_info.skip_zeroes = DEFAULT_SKIP_ZEROES; disasm_info.skip_zeroes_at_end = DEFAULT_SKIP_ZEROES_AT_END; disasm_info.disassembler_needs_relocs = FALSE; @@ -2679,6 +2741,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, bfd *abfd = (bfd *) file; bfd_byte *contents; bfd_size_type amt; + size_t alloced; if (section->start != NULL) { @@ -2691,11 +2754,12 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, section->filename = bfd_get_filename (abfd); section->reloc_info = NULL; section->num_relocs = 0; - section->address = bfd_get_section_vma (abfd, sec); + section->address = bfd_section_vma (sec); section->user_data = sec; - section->size = bfd_get_section_size (sec); - amt = section->size + 1; - if (amt == 0 || amt > bfd_get_file_size (abfd)) + 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) { section->start = NULL; free_debug_section (debug); @@ -2704,7 +2768,7 @@ load_specific_debug_section (enum dwarf_section_display_enum 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)) { @@ -2716,7 +2780,8 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, /* 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; @@ -2864,7 +2929,7 @@ static void dump_dwarf_section (bfd *abfd, asection *section, void *arg ATTRIBUTE_UNUSED) { - const char *name = bfd_get_section_name (abfd, section); + const char *name = bfd_section_name (section); const char *match; int i; @@ -2910,46 +2975,8 @@ dump_dwarf (bfd *abfd) return; } - is_relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0; - - eh_addr_size = bfd_arch_bits_per_address (abfd) / 8; - switch (bfd_get_arch (abfd)) { - case bfd_arch_i386: - switch (bfd_get_mach (abfd)) - { - case bfd_mach_x86_64: - case bfd_mach_x86_64_intel_syntax: - case bfd_mach_x86_64_nacl: - case bfd_mach_x64_32: - case bfd_mach_x64_32_intel_syntax: - case bfd_mach_x64_32_nacl: - init_dwarf_regnames_x86_64 (); - break; - - default: - init_dwarf_regnames_i386 (); - break; - } - break; - - case bfd_arch_iamcu: - init_dwarf_regnames_iamcu (); - break; - - case bfd_arch_aarch64: - init_dwarf_regnames_aarch64(); - break; - - case bfd_arch_s390: - init_dwarf_regnames_s390 (); - break; - - case bfd_arch_riscv: - init_dwarf_regnames_riscv (); - break; - case bfd_arch_s12z: /* S12Z has a 24 bit address space. But the only known producer of dwarf_info encodes addresses into 32 bits. */ @@ -2957,9 +2984,13 @@ dump_dwarf (bfd *abfd) break; default: + eh_addr_size = bfd_arch_bits_per_address (abfd) / 8; break; } + 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); } @@ -2967,7 +2998,8 @@ dump_dwarf (bfd *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; @@ -2990,7 +3022,9 @@ read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr) return NULL; } - *size_ptr = bfd_section_size (abfd, stabsect); + *size_ptr = bfd_section_size (stabsect); + if (entsize_ptr) + *entsize_ptr = stabsect->entsize; return contents; } @@ -3114,11 +3148,11 @@ find_stabs_section (bfd *abfd, asection *section, void *names) { 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); } @@ -3180,6 +3214,149 @@ dump_bfd_header (bfd *abfd) bfd_printf_vma (abfd, abfd->start_address); printf ("\n"); } + + +/* 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[] = {"Header", "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. + + The parent, if there is one, is the default-owned archive member: + avoid importing it into itself. (This does no harm, but looks + confusing.) */ + + if (strcmp (name, ".ctf") != 0) + { + printf (_("\nCTF archive member: %s:\n"), sanitize_string (name)); + ctf_import (ctf, parent); + } + + for (i = 0, 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, *lookparent; + 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)); + } + + lookparent = parenta; + } + else + lookparent = ctfa; + + /* 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 (lookparent, 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); +} static void @@ -3253,7 +3430,7 @@ dump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) bfd_vma addr_offset; bfd_vma start_offset; bfd_vma stop_offset; - unsigned int opb = bfd_octets_per_byte (abfd); + unsigned int opb = bfd_octets_per_byte (abfd, section); /* Bytes per line. */ const int onaline = 16; char buf[64]; @@ -3266,7 +3443,7 @@ dump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) if (! process_section_p (section)) return; - if ((datasize = bfd_section_size (abfd, section)) == 0) + if ((datasize = bfd_section_size (section)) == 0) return; /* Compute the address range to display. */ @@ -3629,7 +3806,7 @@ dump_relocs_in_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) { - arelent **relpp; + arelent **relpp = NULL; long relcount; long relsize; @@ -3640,47 +3817,28 @@ dump_relocs_in_section (bfd *abfd, || ((section->flags & SEC_RELOC) == 0)) return; - relsize = bfd_get_reloc_upper_bound (abfd, section); - if (relsize < 0) - bfd_fatal (bfd_get_filename (abfd)); - printf ("RELOCATION RECORDS FOR [%s]:", sanitize_string (section->name)); + relsize = bfd_get_reloc_upper_bound (abfd, section); if (relsize == 0) { printf (" (none)\n\n"); return; } - if ((bfd_get_file_flags (abfd) & (BFD_IN_MEMORY | BFD_LINKER_CREATED)) == 0 - && (/* Check that the size of the relocs is reasonable. Note that some - file formats, eg aout, can have relocs whose internal size is - larger than their external size, thus we check the size divided - by four against the file size. See PR 23931 for an example of - this. */ - ((ufile_ptr) (relsize / 4) > bfd_get_file_size (abfd)) - /* Also check the section's reloc count since if this is negative - (or very large) the computation in bfd_get_reloc_upper_bound - may have resulted in returning a small, positive integer. - See PR 22508 for a reproducer. - - Note - we check against file size rather than section size as - it is possible for there to be more relocs that apply to a - section than there are bytes in that section. */ - || (section->reloc_count > bfd_get_file_size (abfd)))) + if (relsize < 0) + relcount = relsize; + else { - printf (" (too many: %#x relocs)\n", section->reloc_count); - bfd_set_error (bfd_error_file_truncated); - bfd_fatal (bfd_get_filename (abfd)); + relpp = (arelent **) xmalloc (relsize); + relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); } - relpp = (arelent **) xmalloc (relsize); - relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); - if (relcount < 0) { printf ("\n"); - non_fatal (_("failed to read relocs in: %s"), sanitize_string (bfd_get_filename (abfd))); + non_fatal (_("failed to read relocs in: %s"), + sanitize_string (bfd_get_filename (abfd))); bfd_fatal (_("error message was")); } else if (relcount == 0) @@ -3765,11 +3923,25 @@ adjust_addresses (bfd *abfd ATTRIBUTE_UNUSED, } } +/* 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)) @@ -3800,6 +3972,18 @@ dump_bfd (bfd *abfd, bfd_boolean is_mainfile) } } + /* 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. */ @@ -3885,6 +4069,8 @@ dump_bfd (bfd *abfd, bfd_boolean is_mainfile) 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) @@ -4282,6 +4468,15 @@ main (int argc, char **argv) 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; @@ -4324,6 +4519,14 @@ main (int argc, char **argv) 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; @@ -4383,6 +4586,9 @@ main (int argc, char **argv) } free_only_list (); + free (dump_ctf_section_name); + free (dump_ctf_parent_name); + free ((void *) source_comment); END_PROGRESS (program_name);