+ case DW_CFA_def_cfa:
+ READ_SLEB (fc->cfa_reg);
+ READ_ULEB (fc->cfa_offset);
+ fc->cfa_exp = 0;
+ if (! do_debug_frames_interp)
+ printf (" DW_CFA_def_cfa: %s ofs %d\n",
+ regname (fc->cfa_reg, 0), (int) fc->cfa_offset);
+ break;
+
+ case DW_CFA_def_cfa_register:
+ READ_SLEB (fc->cfa_reg);
+ fc->cfa_exp = 0;
+ if (! do_debug_frames_interp)
+ printf (" DW_CFA_def_cfa_register: %s\n",
+ regname (fc->cfa_reg, 0));
+ break;
+
+ case DW_CFA_def_cfa_offset:
+ READ_ULEB (fc->cfa_offset);
+ if (! do_debug_frames_interp)
+ printf (" DW_CFA_def_cfa_offset: %d\n", (int) fc->cfa_offset);
+ break;
+
+ case DW_CFA_nop:
+ if (! do_debug_frames_interp)
+ printf (" DW_CFA_nop\n");
+ break;
+
+ case DW_CFA_def_cfa_expression:
+ READ_ULEB (ul);
+ if (start >= block_end || ul > (unsigned long) (block_end - start))
+ {
+ printf (_(" DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
+ break;
+ }
+ if (! do_debug_frames_interp)
+ {
+ printf (" DW_CFA_def_cfa_expression (");
+ decode_location_expression (start, eh_addr_size, 0, -1,
+ ul, 0, section);
+ printf (")\n");
+ }
+ fc->cfa_exp = 1;
+ start += ul;
+ break;
+
+ case DW_CFA_expression:
+ READ_ULEB (reg);
+ READ_ULEB (ul);
+ if (reg >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ /* PR 17512: file: 069-133014-0.006. */
+ /* PR 17512: file: 98c02eb4. */
+ tmp = start + ul;
+ if (start >= block_end || tmp > block_end || tmp < start)
+ {
+ printf (_(" DW_CFA_expression: <corrupt len %lu>\n"), ul);
+ break;
+ }
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ {
+ printf (" DW_CFA_expression: %s%s (",
+ reg_prefix, regname (reg, 0));
+ decode_location_expression (start, eh_addr_size, 0, -1,
+ ul, 0, section);
+ printf (")\n");
+ }
+ if (*reg_prefix == '\0')
+ fc->col_type[reg] = DW_CFA_expression;
+ start = tmp;
+ break;
+
+ case DW_CFA_val_expression:
+ READ_ULEB (reg);
+ READ_ULEB (ul);
+ if (reg >= (unsigned int) fc->ncols)
+ reg_prefix = bad_reg;
+ tmp = start + ul;
+ if (start >= block_end || tmp > block_end || tmp < start)
+ {
+ printf (" DW_CFA_val_expression: <corrupt len %lu>\n", ul);
+ break;
+ }
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ {
+ printf (" DW_CFA_val_expression: %s%s (",
+ reg_prefix, regname (reg, 0));
+ decode_location_expression (start, eh_addr_size, 0, -1,
+ ul, 0, section);
+ printf (")\n");
+ }
+ if (*reg_prefix == '\0')
+ fc->col_type[reg] = DW_CFA_val_expression;
+ start = tmp;
+ break;
+
+ case DW_CFA_offset_extended_sf:
+ READ_ULEB (reg);
+ READ_SLEB (l);
+ if (frame_need_space (fc, reg) < 0)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_offset_extended_sf: %s%s at cfa%+ld\n",
+ reg_prefix, regname (reg, 0),
+ (long)(l * fc->data_factor));
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_offset;
+ fc->col_offset[reg] = l * fc->data_factor;
+ }
+ break;
+
+ case DW_CFA_val_offset_sf:
+ READ_ULEB (reg);
+ READ_SLEB (l);
+ if (frame_need_space (fc, reg) < 0)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_val_offset_sf: %s%s is cfa%+ld\n",
+ reg_prefix, regname (reg, 0),
+ (long)(l * fc->data_factor));
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_val_offset;
+ fc->col_offset[reg] = l * fc->data_factor;
+ }
+ break;
+
+ case DW_CFA_def_cfa_sf:
+ READ_SLEB (fc->cfa_reg);
+ READ_ULEB (fc->cfa_offset);
+ fc->cfa_offset = fc->cfa_offset * fc->data_factor;
+ fc->cfa_exp = 0;
+ if (! do_debug_frames_interp)
+ printf (" DW_CFA_def_cfa_sf: %s ofs %d\n",
+ regname (fc->cfa_reg, 0), (int) fc->cfa_offset);
+ break;
+
+ case DW_CFA_def_cfa_offset_sf:
+ READ_ULEB (fc->cfa_offset);
+ fc->cfa_offset *= fc->data_factor;
+ if (! do_debug_frames_interp)
+ printf (" DW_CFA_def_cfa_offset_sf: %d\n", (int) fc->cfa_offset);
+ break;
+
+ case DW_CFA_MIPS_advance_loc8:
+ SAFE_BYTE_GET_AND_INC (ofs, start, 8, block_end);
+ if (do_debug_frames_interp)
+ frame_display_row (fc, &need_col_headers, &max_regs);
+ else
+ printf (" DW_CFA_MIPS_advance_loc8: %ld to %s\n",
+ (unsigned long) (ofs * fc->code_factor),
+ dwarf_vmatoa_1 (NULL,
+ fc->pc_begin + ofs * fc->code_factor,
+ fc->ptr_size));
+ fc->pc_begin += ofs * fc->code_factor;
+ break;
+
+ case DW_CFA_GNU_window_save:
+ if (! do_debug_frames_interp)
+ printf (" DW_CFA_GNU_window_save\n");
+ break;
+
+ case DW_CFA_GNU_args_size:
+ READ_ULEB (ul);
+ if (! do_debug_frames_interp)
+ printf (" DW_CFA_GNU_args_size: %ld\n", ul);
+ break;
+
+ case DW_CFA_GNU_negative_offset_extended:
+ READ_ULEB (reg);
+ READ_SLEB (l);
+ l = - l;
+ if (frame_need_space (fc, reg) < 0)
+ reg_prefix = bad_reg;
+ if (! do_debug_frames_interp || *reg_prefix != '\0')
+ printf (" DW_CFA_GNU_negative_offset_extended: %s%s at cfa%+ld\n",
+ reg_prefix, regname (reg, 0),
+ (long)(l * fc->data_factor));
+ if (*reg_prefix == '\0')
+ {
+ fc->col_type[reg] = DW_CFA_offset;
+ fc->col_offset[reg] = l * fc->data_factor;
+ }
+ break;
+
+ default:
+ if (op >= DW_CFA_lo_user && op <= DW_CFA_hi_user)
+ printf (_(" DW_CFA_??? (User defined call frame op: %#x)\n"), op);
+ else
+ warn (_("Unsupported or unknown Dwarf Call Frame Instruction number: %#x\n"), op);
+ start = block_end;
+ }
+ }
+
+ /* Interpret the CFA - as long as it is not completely full of NOPs. */
+ if (do_debug_frames_interp && ! all_nops)
+ frame_display_row (fc, &need_col_headers, &max_regs);
+
+ start = block_end;
+ eh_addr_size = saved_eh_addr_size;
+ }
+
+ printf ("\n");
+
+ return 1;
+}
+
+#undef GET
+
+static int
+display_debug_names (struct dwarf_section *section, void *file)
+{
+ unsigned char *hdrptr = section->start;
+ dwarf_vma unit_length;
+ unsigned char *unit_start;
+ const unsigned char *const section_end = section->start + section->size;
+ unsigned char *unit_end;
+
+ printf (_("Contents of the %s section:\n"), section->name);
+
+ load_debug_section (str, file);
+
+ for (; hdrptr < section_end; hdrptr = unit_end)
+ {
+ unsigned int offset_size;
+ uint16_t dwarf_version, padding;
+ uint32_t comp_unit_count, local_type_unit_count, foreign_type_unit_count;
+ uint32_t bucket_count, name_count, abbrev_table_size;
+ uint32_t augmentation_string_size;
+ unsigned int i;
+
+ unit_start = hdrptr;
+
+ /* Get and check the length of the block. */
+ SAFE_BYTE_GET_AND_INC (unit_length, hdrptr, 4, section_end);
+
+ if (unit_length == 0xffffffff)
+ {
+ /* This section is 64-bit DWARF. */
+ SAFE_BYTE_GET_AND_INC (unit_length, hdrptr, 8, section_end);
+ offset_size = 8;
+ }
+ else
+ offset_size = 4;
+ unit_end = hdrptr + unit_length;
+
+ if ((hdrptr - section->start) + unit_length > section->size)
+ {
+ warn (_("The length field (0x%lx) for unit 0x%lx in the debug_names "
+ "header is wrong - the section is too small\n"),
+ (long) unit_length, (long) (unit_start - section->start));
+ return 0;
+ }
+
+ /* Get and check the version number. */
+ SAFE_BYTE_GET_AND_INC (dwarf_version, hdrptr, 2, unit_end);
+ printf (_("Version %ld\n"), (long) dwarf_version);
+
+ /* Prior versions did not exist, and future versions may not be
+ backwards compatible. */
+ if (dwarf_version != 5)
+ {
+ warn (_("Only DWARF version 5 .debug_names "
+ "is currently supported.\n"));
+ return 0;
+ }
+
+ SAFE_BYTE_GET_AND_INC (padding, hdrptr, 2, unit_end);
+ if (padding != 0)
+ warn (_("Padding field of .debug_names must be 0 (found 0x%x)\n"),
+ padding);
+
+ SAFE_BYTE_GET_AND_INC (comp_unit_count, hdrptr, 4, unit_end);
+ if (comp_unit_count == 0)
+ warn (_("Compilation unit count must be >= 1 in .debug_names\n"));
+
+ SAFE_BYTE_GET_AND_INC (local_type_unit_count, hdrptr, 4, unit_end);
+ SAFE_BYTE_GET_AND_INC (foreign_type_unit_count, hdrptr, 4, unit_end);
+ SAFE_BYTE_GET_AND_INC (bucket_count, hdrptr, 4, unit_end);
+ SAFE_BYTE_GET_AND_INC (name_count, hdrptr, 4, unit_end);
+ SAFE_BYTE_GET_AND_INC (abbrev_table_size, hdrptr, 4, unit_end);
+
+ SAFE_BYTE_GET_AND_INC (augmentation_string_size, hdrptr, 4, unit_end);
+ if (augmentation_string_size % 4 != 0)
+ {
+ warn (_("Augmentation string length %u must be rounded up "
+ "to a multiple of 4 in .debug_names.\n"),
+ augmentation_string_size);
+ augmentation_string_size += (-augmentation_string_size) & 3;
+ }
+ printf (_("Augmentation string:"));
+ for (i = 0; i < augmentation_string_size; i++)
+ {
+ unsigned char uc;
+
+ SAFE_BYTE_GET_AND_INC (uc, hdrptr, 1, unit_end);
+ printf (" %02x", uc);
+ }
+ putchar ('\n');
+ putchar ('\n');
+
+ printf (_("CU table:\n"));
+ for (i = 0; i < comp_unit_count; i++)
+ {
+ uint64_t cu_offset;
+
+ SAFE_BYTE_GET_AND_INC (cu_offset, hdrptr, offset_size, unit_end);
+ printf (_("[%3u] 0x%lx\n"), i, (unsigned long) cu_offset);
+ }
+ putchar ('\n');
+
+ printf (_("TU table:\n"));
+ for (i = 0; i < local_type_unit_count; i++)
+ {
+ uint64_t tu_offset;
+
+ SAFE_BYTE_GET_AND_INC (tu_offset, hdrptr, offset_size, unit_end);
+ printf (_("[%3u] 0x%lx\n"), i, (unsigned long) tu_offset);
+ }
+ putchar ('\n');
+
+ printf (_("Foreign TU table:\n"));
+ for (i = 0; i < foreign_type_unit_count; i++)
+ {
+ uint64_t signature;
+
+ SAFE_BYTE_GET_AND_INC (signature, hdrptr, 8, unit_end);
+ printf (_("[%3u] "), i);
+ print_dwarf_vma (signature, 8);
+ putchar ('\n');
+ }
+ putchar ('\n');
+
+ const uint32_t *const hash_table_buckets = (uint32_t *) hdrptr;
+ hdrptr += bucket_count * sizeof (uint32_t);
+ const uint32_t *const hash_table_hashes = (uint32_t *) hdrptr;
+ hdrptr += name_count * sizeof (uint32_t);
+ unsigned char *const name_table_string_offsets = hdrptr;
+ hdrptr += name_count * offset_size;
+ unsigned char *const name_table_entry_offsets = hdrptr;
+ hdrptr += name_count * offset_size;
+ unsigned char *const abbrev_table = hdrptr;
+ hdrptr += abbrev_table_size;
+ const unsigned char *const abbrev_table_end = hdrptr;
+ unsigned char *const entry_pool = hdrptr;
+ if (hdrptr > unit_end)
+ {
+ warn (_("Entry pool offset (0x%lx) exceeds unit size 0x%lx "
+ "for unit 0x%lx in the debug_names\n"),
+ (long) (hdrptr - section->start),
+ (long) (unit_end - section->start),
+ (long) (unit_start - section->start));
+ return 0;
+ }
+
+ size_t buckets_filled = 0;
+ size_t bucketi;
+ for (bucketi = 0; bucketi < bucket_count; bucketi++)
+ {
+ const uint32_t bucket = hash_table_buckets[bucketi];
+
+ if (bucket != 0)
+ ++buckets_filled;
+ }
+ printf (_("Used %zu of %lu buckets.\n"), buckets_filled,
+ (unsigned long) bucket_count);
+
+ uint32_t hash_prev;
+ size_t hash_clash_count = 0;
+ size_t longest_clash = 0;
+ size_t this_length = 0;
+ size_t hashi;
+ for (hashi = 0; hashi < name_count; hashi++)
+ {
+ const uint32_t hash_this = hash_table_hashes[hashi];
+
+ if (hashi > 0)
+ {
+ if (hash_prev % bucket_count == hash_this % bucket_count)
+ {
+ ++hash_clash_count;
+ ++this_length;
+ longest_clash = MAX (longest_clash, this_length);
+ }
+ else
+ this_length = 0;
+ }
+ hash_prev = hash_this;
+ }
+ printf (_("Out of %lu items there are %zu bucket clashes"
+ " (longest of %zu entries).\n"),
+ (unsigned long) name_count, hash_clash_count, longest_clash);
+ assert (name_count == buckets_filled + hash_clash_count);
+
+ struct abbrev_lookup_entry
+ {
+ dwarf_vma abbrev_tag;
+ unsigned char *abbrev_lookup_ptr;
+ };
+ struct abbrev_lookup_entry *abbrev_lookup = NULL;
+ size_t abbrev_lookup_used = 0;
+ size_t abbrev_lookup_allocated = 0;
+
+ unsigned char *abbrevptr = abbrev_table;
+ for (;;)
+ {
+ unsigned int bytes_read;
+ const dwarf_vma abbrev_tag = read_uleb128 (abbrevptr, &bytes_read,
+ abbrev_table_end);
+ abbrevptr += bytes_read;
+ if (abbrev_tag == 0)
+ break;
+ if (abbrev_lookup_used == abbrev_lookup_allocated)
+ {
+ abbrev_lookup_allocated = MAX (0x100,
+ abbrev_lookup_allocated * 2);
+ abbrev_lookup = xrealloc (abbrev_lookup,
+ (abbrev_lookup_allocated
+ * sizeof (*abbrev_lookup)));
+ }
+ assert (abbrev_lookup_used < abbrev_lookup_allocated);
+ struct abbrev_lookup_entry *entry;
+ for (entry = abbrev_lookup;
+ entry < abbrev_lookup + abbrev_lookup_used;
+ entry++)
+ if (entry->abbrev_tag == abbrev_tag)
+ {
+ warn (_("Duplicate abbreviation tag %lu "
+ "in unit 0x%lx in the debug_names\n"),
+ (long) abbrev_tag, (long) (unit_start - section->start));
+ break;
+ }
+ entry = &abbrev_lookup[abbrev_lookup_used++];
+ entry->abbrev_tag = abbrev_tag;
+ entry->abbrev_lookup_ptr = abbrevptr;
+
+ /* Skip DWARF tag. */
+ read_uleb128 (abbrevptr, &bytes_read, abbrev_table_end);
+ abbrevptr += bytes_read;
+ for (;;)
+ {
+ const dwarf_vma xindex = read_uleb128 (abbrevptr,
+ &bytes_read,
+ abbrev_table_end);
+ abbrevptr += bytes_read;
+ const dwarf_vma form = read_uleb128 (abbrevptr, &bytes_read,
+ abbrev_table_end);
+ abbrevptr += bytes_read;
+ if (xindex == 0 && form == 0)
+ break;
+ }
+ }
+
+ printf (_("\nSymbol table:\n"));
+ uint32_t namei;
+ for (namei = 0; namei < name_count; ++namei)
+ {
+ uint64_t string_offset, entry_offset;
+
+ SAFE_BYTE_GET (string_offset,
+ name_table_string_offsets + namei * offset_size,
+ offset_size, unit_end);
+ SAFE_BYTE_GET (entry_offset,
+ name_table_entry_offsets + namei * offset_size,
+ offset_size, unit_end);
+
+ printf ("[%3u] #%08x %s:", namei, hash_table_hashes[namei],
+ fetch_indirect_string (string_offset));
+
+ unsigned char *entryptr = entry_pool + entry_offset;
+
+ // We need to scan first whether there is a single or multiple
+ // entries. TAGNO is -2 for the first entry, it is -1 for the
+ // initial tag read of the second entry, then it becomes 0 for the
+ // first entry for real printing etc.
+ int tagno = -2;
+ /* Initialize it due to a false compiler warning. */
+ dwarf_vma second_abbrev_tag = -1;
+ for (;;)
+ {
+ unsigned int bytes_read;
+ const dwarf_vma abbrev_tag = read_uleb128 (entryptr, &bytes_read,
+ unit_end);
+ entryptr += bytes_read;
+ if (tagno == -1)
+ {
+ second_abbrev_tag = abbrev_tag;
+ tagno = 0;
+ entryptr = entry_pool + entry_offset;
+ continue;
+ }
+ if (abbrev_tag == 0)
+ break;
+ if (tagno >= 0)
+ printf ("%s<%lu>",
+ (tagno == 0 && second_abbrev_tag == 0 ? " " : "\n\t"),
+ (unsigned long) abbrev_tag);
+
+ const struct abbrev_lookup_entry *entry;
+ for (entry = abbrev_lookup;
+ entry < abbrev_lookup + abbrev_lookup_used;
+ entry++)
+ if (entry->abbrev_tag == abbrev_tag)
+ break;
+ if (entry >= abbrev_lookup + abbrev_lookup_used)
+ {
+ warn (_("Undefined abbreviation tag %lu "
+ "in unit 0x%lx in the debug_names\n"),
+ (long) abbrev_tag,
+ (long) (unit_start - section->start));
+ break;
+ }
+ abbrevptr = entry->abbrev_lookup_ptr;
+ const dwarf_vma dwarf_tag = read_uleb128 (abbrevptr, &bytes_read,
+ abbrev_table_end);
+ abbrevptr += bytes_read;
+ if (tagno >= 0)
+ printf (" %s", get_TAG_name (dwarf_tag));
+ for (;;)
+ {
+ const dwarf_vma xindex = read_uleb128 (abbrevptr,
+ &bytes_read,
+ abbrev_table_end);
+ abbrevptr += bytes_read;
+ const dwarf_vma form = read_uleb128 (abbrevptr, &bytes_read,
+ abbrev_table_end);
+ abbrevptr += bytes_read;
+ if (xindex == 0 && form == 0)
+ break;
+
+ if (tagno >= 0)
+ printf (" %s", get_IDX_name (xindex));
+ entryptr = read_and_display_attr_value (0, form, 0, entryptr,
+ unit_end, 0, 0,
+ offset_size,
+ dwarf_version, NULL,
+ (tagno < 0), NULL,
+ NULL, '=');
+ }
+ ++tagno;
+ }
+ if (tagno <= 0)
+ printf (_(" <no entries>"));
+ putchar ('\n');
+ }
+
+ free (abbrev_lookup);
+ }
+
+ return 1;
+}
+
+static int
+display_gdb_index (struct dwarf_section *section,
+ void *file ATTRIBUTE_UNUSED)
+{
+ unsigned char *start = section->start;
+ uint32_t version;
+ uint32_t cu_list_offset, tu_list_offset;
+ uint32_t address_table_offset, symbol_table_offset, constant_pool_offset;
+ unsigned int cu_list_elements, tu_list_elements;
+ unsigned int address_table_size, symbol_table_slots;
+ unsigned char *cu_list, *tu_list;
+ unsigned char *address_table, *symbol_table, *constant_pool;
+ unsigned int i;
+
+ /* The documentation for the format of this file is in gdb/dwarf2read.c. */
+
+ printf (_("Contents of the %s section:\n"), section->name);
+
+ if (section->size < 6 * sizeof (uint32_t))
+ {
+ warn (_("Truncated header in the %s section.\n"), section->name);
+ return 0;
+ }
+
+ version = byte_get_little_endian (start, 4);
+ printf (_("Version %ld\n"), (long) version);
+
+ /* Prior versions are obsolete, and future versions may not be
+ backwards compatible. */
+ if (version < 3 || version > 8)
+ {
+ warn (_("Unsupported version %lu.\n"), (unsigned long) version);
+ return 0;
+ }
+ if (version < 4)
+ warn (_("The address table data in version 3 may be wrong.\n"));
+ if (version < 5)
+ warn (_("Version 4 does not support case insensitive lookups.\n"));
+ if (version < 6)
+ warn (_("Version 5 does not include inlined functions.\n"));
+ if (version < 7)
+ warn (_("Version 6 does not include symbol attributes.\n"));
+ /* Version 7 indices generated by Gold have bad type unit references,
+ PR binutils/15021. But we don't know if the index was generated by
+ Gold or not, so to avoid worrying users with gdb-generated indices
+ we say nothing for version 7 here. */
+
+ cu_list_offset = byte_get_little_endian (start + 4, 4);
+ tu_list_offset = byte_get_little_endian (start + 8, 4);
+ address_table_offset = byte_get_little_endian (start + 12, 4);
+ symbol_table_offset = byte_get_little_endian (start + 16, 4);
+ constant_pool_offset = byte_get_little_endian (start + 20, 4);
+
+ if (cu_list_offset > section->size
+ || tu_list_offset > section->size
+ || address_table_offset > section->size
+ || symbol_table_offset > section->size
+ || constant_pool_offset > section->size)
+ {
+ warn (_("Corrupt header in the %s section.\n"), section->name);
+ return 0;
+ }
+
+ /* PR 17531: file: 418d0a8a. */
+ if (tu_list_offset < cu_list_offset)
+ {
+ warn (_("TU offset (%x) is less than CU offset (%x)\n"),
+ tu_list_offset, cu_list_offset);
+ return 0;
+ }
+
+ cu_list_elements = (tu_list_offset - cu_list_offset) / 8;
+
+ if (address_table_offset < tu_list_offset)
+ {
+ warn (_("Address table offset (%x) is less than TU offset (%x)\n"),
+ address_table_offset, tu_list_offset);
+ return 0;
+ }
+
+ tu_list_elements = (address_table_offset - tu_list_offset) / 8;
+
+ /* PR 17531: file: 18a47d3d. */
+ if (symbol_table_offset < address_table_offset)
+ {
+ warn (_("Symbol table offset (%xl) is less then Address table offset (%x)\n"),
+ symbol_table_offset, address_table_offset);
+ return 0;
+ }
+
+ address_table_size = symbol_table_offset - address_table_offset;
+
+ if (constant_pool_offset < symbol_table_offset)
+ {
+ warn (_("Constant pool offset (%x) is less than symbol table offset (%x)\n"),
+ constant_pool_offset, symbol_table_offset);
+ return 0;
+ }
+
+ symbol_table_slots = (constant_pool_offset - symbol_table_offset) / 8;
+
+ cu_list = start + cu_list_offset;
+ tu_list = start + tu_list_offset;
+ address_table = start + address_table_offset;
+ symbol_table = start + symbol_table_offset;
+ constant_pool = start + constant_pool_offset;
+
+ if (address_table + address_table_size > section->start + section->size)
+ {
+ warn (_("Address table extends beyond end of section.\n"));
+ return 0;
+ }
+
+ printf (_("\nCU table:\n"));
+ for (i = 0; i < cu_list_elements; i += 2)
+ {
+ uint64_t cu_offset = byte_get_little_endian (cu_list + i * 8, 8);
+ uint64_t cu_length = byte_get_little_endian (cu_list + i * 8 + 8, 8);
+
+ printf (_("[%3u] 0x%lx - 0x%lx\n"), i / 2,
+ (unsigned long) cu_offset,
+ (unsigned long) (cu_offset + cu_length - 1));
+ }
+
+ printf (_("\nTU table:\n"));
+ for (i = 0; i < tu_list_elements; i += 3)
+ {
+ uint64_t tu_offset = byte_get_little_endian (tu_list + i * 8, 8);
+ uint64_t type_offset = byte_get_little_endian (tu_list + i * 8 + 8, 8);
+ uint64_t signature = byte_get_little_endian (tu_list + i * 8 + 16, 8);
+
+ printf (_("[%3u] 0x%lx 0x%lx "), i / 3,
+ (unsigned long) tu_offset,
+ (unsigned long) type_offset);
+ print_dwarf_vma (signature, 8);
+ printf ("\n");
+ }
+
+ printf (_("\nAddress table:\n"));
+ for (i = 0; i < address_table_size && i <= address_table_size - (2 * 8 + 4);
+ i += 2 * 8 + 4)
+ {
+ uint64_t low = byte_get_little_endian (address_table + i, 8);
+ uint64_t high = byte_get_little_endian (address_table + i + 8, 8);
+ uint32_t cu_index = byte_get_little_endian (address_table + i + 16, 4);
+
+ print_dwarf_vma (low, 8);
+ print_dwarf_vma (high, 8);
+ printf (_("%lu\n"), (unsigned long) cu_index);
+ }
+
+ printf (_("\nSymbol table:\n"));
+ for (i = 0; i < symbol_table_slots; ++i)
+ {
+ uint32_t name_offset = byte_get_little_endian (symbol_table + i * 8, 4);
+ uint32_t cu_vector_offset = byte_get_little_endian (symbol_table + i * 8 + 4, 4);
+ uint32_t num_cus, cu;
+
+ if (name_offset != 0
+ || cu_vector_offset != 0)
+ {
+ unsigned int j;
+ unsigned char * adr;
+
+ adr = constant_pool + name_offset;
+ /* PR 17531: file: 5b7b07ad. */
+ if (adr < constant_pool || adr >= section->start + section->size)
+ {
+ printf (_("[%3u] <corrupt offset: %x>"), i, name_offset);
+ warn (_("Corrupt name offset of 0x%x found for symbol table slot %d\n"),
+ name_offset, i);
+ }
+ else
+ printf ("[%3u] %.*s:", i,
+ (int) (section->size - (constant_pool_offset + name_offset)),
+ constant_pool + name_offset);
+
+ adr = constant_pool + cu_vector_offset;
+ if (adr < constant_pool || adr >= section->start + section->size - 3)
+ {
+ printf (_("<invalid CU vector offset: %x>\n"), cu_vector_offset);
+ warn (_("Corrupt CU vector offset of 0x%x found for symbol table slot %d\n"),
+ cu_vector_offset, i);
+ continue;
+ }
+
+ num_cus = byte_get_little_endian (adr, 4);
+
+ adr = constant_pool + cu_vector_offset + 4 + num_cus * 4;
+ if (num_cus * 4 < num_cus
+ || adr >= section->start + section->size
+ || adr < constant_pool)
+ {
+ printf ("<invalid number of CUs: %d>\n", num_cus);
+ warn (_("Invalid number of CUs (0x%x) for symbol table slot %d\n"),
+ num_cus, i);
+ continue;
+ }
+
+ if (num_cus > 1)
+ printf ("\n");
+
+ for (j = 0; j < num_cus; ++j)
+ {
+ int is_static;
+ gdb_index_symbol_kind kind;
+
+ cu = byte_get_little_endian (constant_pool + cu_vector_offset + 4 + j * 4, 4);
+ is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu);
+ kind = GDB_INDEX_SYMBOL_KIND_VALUE (cu);
+ cu = GDB_INDEX_CU_VALUE (cu);
+ /* Convert to TU number if it's for a type unit. */
+ if (cu >= cu_list_elements / 2)
+ printf ("%cT%lu", num_cus > 1 ? '\t' : ' ',
+ (unsigned long) (cu - cu_list_elements / 2));
+ else
+ printf ("%c%lu", num_cus > 1 ? '\t' : ' ', (unsigned long) cu);
+
+ printf (" [%s, %s]",
+ is_static ? _("static") : _("global"),
+ get_gdb_index_symbol_kind_name (kind));
+ if (num_cus > 1)
+ printf ("\n");
+ }
+ if (num_cus <= 1)
+ printf ("\n");
+ }
+ }
+
+ return 1;
+}
+
+/* Pre-allocate enough space for the CU/TU sets needed. */
+
+static void
+prealloc_cu_tu_list (unsigned int nshndx)
+{
+ if (shndx_pool == NULL)
+ {
+ shndx_pool_size = nshndx;
+ shndx_pool_used = 0;
+ shndx_pool = (unsigned int *) xcmalloc (shndx_pool_size,
+ sizeof (unsigned int));
+ }
+ else
+ {
+ shndx_pool_size = shndx_pool_used + nshndx;
+ shndx_pool = (unsigned int *) xcrealloc (shndx_pool, shndx_pool_size,
+ sizeof (unsigned int));
+ }
+}
+
+static void
+add_shndx_to_cu_tu_entry (unsigned int shndx)
+{
+ if (shndx_pool_used >= shndx_pool_size)
+ {
+ error (_("Internal error: out of space in the shndx pool.\n"));
+ return;
+ }
+ shndx_pool [shndx_pool_used++] = shndx;
+}
+
+static void
+end_cu_tu_entry (void)
+{
+ if (shndx_pool_used >= shndx_pool_size)
+ {
+ error (_("Internal error: out of space in the shndx pool.\n"));
+ return;
+ }
+ shndx_pool [shndx_pool_used++] = 0;
+}
+
+/* Return the short name of a DWARF section given by a DW_SECT enumerator. */
+
+static const char *
+get_DW_SECT_short_name (unsigned int dw_sect)
+{
+ static char buf[16];
+
+ switch (dw_sect)
+ {
+ case DW_SECT_INFO:
+ return "info";
+ case DW_SECT_TYPES:
+ return "types";
+ case DW_SECT_ABBREV:
+ return "abbrev";
+ case DW_SECT_LINE:
+ return "line";
+ case DW_SECT_LOC:
+ return "loc";
+ case DW_SECT_STR_OFFSETS:
+ return "str_off";
+ case DW_SECT_MACINFO:
+ return "macinfo";
+ case DW_SECT_MACRO:
+ return "macro";
+ default:
+ break;
+ }
+
+ snprintf (buf, sizeof (buf), "%d", dw_sect);
+ return buf;
+}
+
+/* Process a CU or TU index. If DO_DISPLAY is true, print the contents.
+ These sections are extensions for Fission.
+ See http://gcc.gnu.org/wiki/DebugFissionDWP. */
+
+static int
+process_cu_tu_index (struct dwarf_section *section, int do_display)
+{
+ unsigned char *phdr = section->start;
+ unsigned char *limit = phdr + section->size;
+ unsigned char *phash;
+ unsigned char *pindex;
+ unsigned char *ppool;
+ unsigned int version;
+ unsigned int ncols = 0;
+ unsigned int nused;
+ unsigned int nslots;
+ unsigned int i;
+ unsigned int j;
+ dwarf_vma signature_high;
+ dwarf_vma signature_low;
+ char buf[64];
+
+ /* PR 17512: file: 002-168123-0.004. */
+ if (phdr == NULL)
+ {
+ warn (_("Section %s is empty\n"), section->name);
+ return 0;
+ }
+ /* PR 17512: file: 002-376-0.004. */
+ if (section->size < 24)
+ {
+ warn (_("Section %s is too small to contain a CU/TU header\n"),
+ section->name);
+ return 0;
+ }
+
+ SAFE_BYTE_GET (version, phdr, 4, limit);
+ if (version >= 2)
+ SAFE_BYTE_GET (ncols, phdr + 4, 4, limit);
+ SAFE_BYTE_GET (nused, phdr + 8, 4, limit);
+ SAFE_BYTE_GET (nslots, phdr + 12, 4, limit);
+
+ phash = phdr + 16;
+ pindex = phash + nslots * 8;
+ ppool = pindex + nslots * 4;