+ lbytes = (bytes > 16 ? 16 : bytes);
+
+ printf (" 0x%8.8lx ", (unsigned long) addr);
+
+ for (j = 0; j < 16; j++)
+ {
+ if (j < lbytes)
+ printf ("%2.2x", start[j]);
+ else
+ printf (" ");
+
+ if ((j & 3) == 3)
+ printf (" ");
+ }
+
+ for (j = 0; j < lbytes; j++)
+ {
+ k = start[j];
+ if (k >= ' ' && k < 0x80)
+ printf ("%c", k);
+ else
+ printf (".");
+ }
+
+ putchar ('\n');
+
+ start += lbytes;
+ addr += lbytes;
+ bytes -= lbytes;
+ }
+
+ putchar ('\n');
+
+ return 1;
+}
+
+static int
+display_debug_info (struct dwarf_section *section, void *file)
+{
+ return process_debug_info (section, file, section->abbrev_sec, FALSE, FALSE);
+}
+
+static int
+display_debug_types (struct dwarf_section *section, void *file)
+{
+ return process_debug_info (section, file, section->abbrev_sec, FALSE, TRUE);
+}
+
+static int
+display_trace_info (struct dwarf_section *section, void *file)
+{
+ return process_debug_info (section, file, section->abbrev_sec, FALSE, TRUE);
+}
+
+static int
+display_debug_aranges (struct dwarf_section *section,
+ void *file ATTRIBUTE_UNUSED)
+{
+ unsigned char *start = section->start;
+ unsigned char *end = start + section->size;
+
+ introduce (section, FALSE);
+
+ /* It does not matter if this load fails,
+ we test for that later on. */
+ load_debug_info (file);
+
+ while (start < end)
+ {
+ unsigned char *hdrptr;
+ DWARF2_Internal_ARange arange;
+ unsigned char *addr_ranges;
+ dwarf_vma length;
+ dwarf_vma address;
+ unsigned long sec_off;
+ unsigned char address_size;
+ int excess;
+ unsigned int offset_size;
+ unsigned int initial_length_size;
+
+ hdrptr = start;
+
+ SAFE_BYTE_GET_AND_INC (arange.ar_length, hdrptr, 4, end);
+ if (arange.ar_length == 0xffffffff)
+ {
+ SAFE_BYTE_GET_AND_INC (arange.ar_length, hdrptr, 8, end);
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
+ }
+
+ sec_off = hdrptr - section->start;
+ if (sec_off + arange.ar_length < sec_off
+ || sec_off + arange.ar_length > section->size)
+ {
+ warn (_("Debug info is corrupted, %s header at %#lx has length %s\n"),
+ section->name,
+ sec_off - initial_length_size,
+ dwarf_vmatoa ("x", arange.ar_length));
+ break;
+ }
+
+ SAFE_BYTE_GET_AND_INC (arange.ar_version, hdrptr, 2, end);
+ SAFE_BYTE_GET_AND_INC (arange.ar_info_offset, hdrptr, offset_size, end);
+
+ if (num_debug_info_entries != DEBUG_INFO_UNAVAILABLE
+ && num_debug_info_entries > 0
+ && find_debug_info_for_offset (arange.ar_info_offset) == NULL)
+ warn (_(".debug_info offset of 0x%lx in %s section does not point to a CU header.\n"),
+ (unsigned long) arange.ar_info_offset, section->name);
+
+ SAFE_BYTE_GET_AND_INC (arange.ar_pointer_size, hdrptr, 1, end);
+ SAFE_BYTE_GET_AND_INC (arange.ar_segment_size, hdrptr, 1, end);
+
+ if (arange.ar_version != 2 && arange.ar_version != 3)
+ {
+ /* PR 19872: A version number of 0 probably means that there is
+ padding at the end of the .debug_aranges section. Gold puts
+ it there when performing an incremental link, for example.
+ So do not generate a warning in this case. */
+ if (arange.ar_version)
+ warn (_("Only DWARF 2 and 3 aranges are currently supported.\n"));
+ break;
+ }
+
+ printf (_(" Length: %ld\n"),
+ (long) arange.ar_length);
+ printf (_(" Version: %d\n"), arange.ar_version);
+ printf (_(" Offset into .debug_info: 0x%lx\n"),
+ (unsigned long) arange.ar_info_offset);
+ printf (_(" Pointer Size: %d\n"), arange.ar_pointer_size);
+ printf (_(" Segment Size: %d\n"), arange.ar_segment_size);
+
+ address_size = arange.ar_pointer_size + arange.ar_segment_size;
+
+ /* PR 17512: file: 001-108546-0.001:0.1. */
+ if (address_size == 0 || address_size > 8)
+ {
+ error (_("Invalid address size in %s section!\n"),
+ section->name);
+ break;
+ }
+
+ /* The DWARF spec does not require that the address size be a power
+ of two, but we do. This will have to change if we ever encounter
+ an uneven architecture. */
+ if ((address_size & (address_size - 1)) != 0)
+ {
+ warn (_("Pointer size + Segment size is not a power of two.\n"));
+ break;
+ }
+
+ if (address_size > 4)
+ printf (_("\n Address Length\n"));
+ else
+ printf (_("\n Address Length\n"));
+
+ addr_ranges = hdrptr;
+
+ /* Must pad to an alignment boundary that is twice the address size. */
+ excess = (hdrptr - start) % (2 * address_size);
+ if (excess)
+ addr_ranges += (2 * address_size) - excess;
+
+ start += arange.ar_length + initial_length_size;
+
+ while (addr_ranges + 2 * address_size <= start)
+ {
+ SAFE_BYTE_GET_AND_INC (address, addr_ranges, address_size, end);
+ SAFE_BYTE_GET_AND_INC (length, addr_ranges, address_size, end);
+
+ printf (" ");
+ print_dwarf_vma (address, address_size);
+ print_dwarf_vma (length, address_size);
+ putchar ('\n');
+ }
+ }
+
+ printf ("\n");
+
+ return 1;
+}
+
+/* Comparison function for qsort. */
+static int
+comp_addr_base (const void * v0, const void * v1)
+{
+ debug_info * info0 = (debug_info *) v0;
+ debug_info * info1 = (debug_info *) v1;
+ return info0->addr_base - info1->addr_base;
+}
+
+/* Display the debug_addr section. */
+static int
+display_debug_addr (struct dwarf_section *section,
+ void *file)
+{
+ debug_info **debug_addr_info;
+ unsigned char *entry;
+ unsigned char *end;
+ unsigned int i;
+ unsigned int count;
+
+ if (section->size == 0)
+ {
+ printf (_("\nThe %s section is empty.\n"), section->name);
+ return 0;
+ }
+
+ if (load_debug_info (file) == 0)
+ {
+ warn (_("Unable to load/parse the .debug_info section, so cannot interpret the %s section.\n"),
+ section->name);
+ return 0;
+ }
+
+ introduce (section, FALSE);
+
+ /* PR 17531: file: cf38d01b.
+ We use xcalloc because a corrupt file may not have initialised all of the
+ fields in the debug_info structure, which means that the sort below might
+ try to move uninitialised data. */
+ debug_addr_info = (debug_info **) xcalloc ((num_debug_info_entries + 1),
+ sizeof (debug_info *));
+
+ count = 0;
+ for (i = 0; i < num_debug_info_entries; i++)
+ if (debug_information [i].addr_base != DEBUG_INFO_UNAVAILABLE)
+ {
+ /* PR 17531: file: cf38d01b. */
+ if (debug_information[i].addr_base >= section->size)
+ warn (_("Corrupt address base (%lx) found in debug section %u\n"),
+ (unsigned long) debug_information[i].addr_base, i);
+ else
+ debug_addr_info [count++] = debug_information + i;
+ }
+
+ /* Add a sentinel to make iteration convenient. */
+ debug_addr_info [count] = (debug_info *) xmalloc (sizeof (debug_info));
+ debug_addr_info [count]->addr_base = section->size;
+ qsort (debug_addr_info, count, sizeof (debug_info *), comp_addr_base);
+
+ for (i = 0; i < count; i++)
+ {
+ unsigned int idx;
+ unsigned int address_size = debug_addr_info [i]->pointer_size;
+
+ printf (_(" For compilation unit at offset 0x%s:\n"),
+ dwarf_vmatoa ("x", debug_addr_info [i]->cu_offset));
+
+ printf (_("\tIndex\tAddress\n"));
+ entry = section->start + debug_addr_info [i]->addr_base;
+ end = section->start + debug_addr_info [i + 1]->addr_base;
+ idx = 0;
+ while (entry < end)
+ {
+ dwarf_vma base = byte_get (entry, address_size);
+ printf (_("\t%d:\t"), idx);
+ print_dwarf_vma (base, address_size);
+ printf ("\n");
+ entry += address_size;
+ idx++;
+ }
+ }
+ printf ("\n");
+
+ free (debug_addr_info);
+ return 1;
+}
+
+/* Display the .debug_str_offsets and .debug_str_offsets.dwo sections. */
+static int
+display_debug_str_offsets (struct dwarf_section *section,
+ void *file ATTRIBUTE_UNUSED)
+{
+ if (section->size == 0)
+ {
+ printf (_("\nThe %s section is empty.\n"), section->name);
+ return 0;
+ }
+ /* TODO: Dump the contents. This is made somewhat difficult by not knowing
+ what the offset size is for this section. */
+ return 1;
+}
+
+/* Each debug_information[x].range_lists[y] gets this representation for
+ sorting purposes. */
+
+struct range_entry
+{
+ /* The debug_information[x].range_lists[y] value. */
+ dwarf_vma ranges_offset;
+
+ /* Original debug_information to find parameters of the data. */
+ debug_info *debug_info_p;
+};
+
+/* Sort struct range_entry in ascending order of its RANGES_OFFSET. */
+
+static int
+range_entry_compar (const void *ap, const void *bp)
+{
+ const struct range_entry *a_re = (const struct range_entry *) ap;
+ const struct range_entry *b_re = (const struct range_entry *) bp;
+ const dwarf_vma a = a_re->ranges_offset;
+ const dwarf_vma b = b_re->ranges_offset;
+
+ return (a > b) - (b > a);
+}
+
+static void
+display_debug_ranges_list (unsigned char *start, unsigned char *finish,
+ unsigned int pointer_size, unsigned long offset,
+ unsigned long base_address)
+{
+ while (start < finish)
+ {
+ dwarf_vma begin;
+ dwarf_vma end;
+
+ SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, finish);
+ if (start >= finish)
+ break;
+ SAFE_SIGNED_BYTE_GET_AND_INC (end, start, pointer_size, finish);
+
+
+ printf (" %8.8lx ", offset);
+
+ if (begin == 0 && end == 0)
+ {
+ printf (_("<End of list>\n"));
+ break;
+ }
+
+ /* Check base address specifiers. */
+ if (is_max_address (begin, pointer_size)
+ && !is_max_address (end, pointer_size))
+ {
+ base_address = end;
+ print_dwarf_vma (begin, pointer_size);
+ print_dwarf_vma (end, pointer_size);
+ printf ("(base address)\n");
+ continue;
+ }
+
+ print_dwarf_vma (begin + base_address, pointer_size);
+ print_dwarf_vma (end + base_address, pointer_size);
+
+ if (begin == end)
+ fputs (_("(start == end)"), stdout);
+ else if (begin > end)
+ fputs (_("(start > end)"), stdout);
+
+ putchar ('\n');
+ }
+}
+
+static void
+display_debug_rnglists_list (unsigned char *start, unsigned char *finish,
+ unsigned int pointer_size, unsigned long offset,
+ unsigned long base_address)
+{
+ unsigned char *next = start;
+
+ while (1)
+ {
+ unsigned long off = offset + (start - next);
+ enum dwarf_range_list_entry rlet;
+ /* Initialize it due to a false compiler warning. */
+ dwarf_vma begin = -1, length, end = -1;
+ unsigned int bytes_read;
+
+ if (start + 1 > finish)
+ {
+ warn (_("Range list starting at offset 0x%lx is not terminated.\n"),
+ offset);
+ break;
+ }
+
+ printf (" %8.8lx ", off);
+
+ SAFE_BYTE_GET_AND_INC (rlet, start, 1, finish);
+
+ switch (rlet)
+ {
+ case DW_RLE_end_of_list:
+ printf (_("<End of list>\n"));
+ break;
+ case DW_RLE_base_address:
+ SAFE_BYTE_GET_AND_INC (base_address, start, pointer_size, finish);
+ print_dwarf_vma (base_address, pointer_size);
+ printf (_("(base address)\n"));
+ break;
+ case DW_RLE_start_length:
+ SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, finish);
+ length = read_uleb128 (start, &bytes_read, finish);
+ start += bytes_read;
+ end = begin + length;
+ break;
+ case DW_RLE_offset_pair:
+ begin = read_uleb128 (start, &bytes_read, finish);
+ start += bytes_read;
+ end = read_uleb128 (start, &bytes_read, finish);
+ start += bytes_read;
+ break;
+ case DW_RLE_start_end:
+ SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, finish);
+ SAFE_BYTE_GET_AND_INC (end, start, pointer_size, finish);
+ break;
+ default:
+ error (_("Invalid range list entry type %d\n"), rlet);
+ rlet = DW_RLE_end_of_list;
+ break;
+ }
+ if (rlet == DW_RLE_end_of_list)
+ break;
+ if (rlet == DW_RLE_base_address)
+ continue;
+
+ print_dwarf_vma (begin + base_address, pointer_size);
+ print_dwarf_vma (end + base_address, pointer_size);
+
+ if (begin == end)
+ fputs (_("(start == end)"), stdout);
+ else if (begin > end)
+ fputs (_("(start > end)"), stdout);
+
+ putchar ('\n');
+ }
+}
+
+static int
+display_debug_ranges (struct dwarf_section *section,
+ void *file ATTRIBUTE_UNUSED)
+{
+ unsigned char *start = section->start;
+ unsigned char *last_start = start;
+ unsigned long bytes = section->size;
+ unsigned char *section_begin = start;
+ unsigned char *finish = start + bytes;
+ unsigned int num_range_list, i;
+ struct range_entry *range_entries, *range_entry_fill;
+ int is_rnglists = strstr (section->name, "debug_rnglists") != NULL;
+ /* Initialize it due to a false compiler warning. */
+ unsigned char address_size = 0;
+
+ if (bytes == 0)
+ {
+ printf (_("\nThe %s section is empty.\n"), section->name);
+ return 0;
+ }
+
+ if (is_rnglists)
+ {
+ dwarf_vma initial_length;
+ unsigned int initial_length_size;
+ unsigned char segment_selector_size;
+ unsigned int offset_size, offset_entry_count;
+ unsigned short version;
+
+ /* Get and check the length of the block. */
+ SAFE_BYTE_GET_AND_INC (initial_length, start, 4, finish);
+
+ if (initial_length == 0xffffffff)
+ {
+ /* This section is 64-bit DWARF 3. */
+ SAFE_BYTE_GET_AND_INC (initial_length, start, 8, finish);
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
+ }
+
+ if (initial_length + initial_length_size > section->size)
+ {
+ /* If the length field has a relocation against it, then we should
+ not complain if it is inaccurate (and probably negative).
+ It is copied from .debug_line handling code. */
+ if (reloc_at (section, (start - section->start) - offset_size))
+ {
+ initial_length = (finish - start) - initial_length_size;
+ }
+ else
+ {
+ warn (_("The length field (0x%lx) in the debug_rnglists header is wrong - the section is too small\n"),
+ (long) initial_length);
+ return 0;
+ }
+ }
+
+ /* Get and check the version number. */
+ SAFE_BYTE_GET_AND_INC (version, start, 2, finish);
+
+ if (version != 5)
+ {
+ warn (_("Only DWARF version 5 debug_rnglists info "
+ "is currently supported.\n"));
+ return 0;
+ }
+
+ SAFE_BYTE_GET_AND_INC (address_size, start, 1, finish);
+
+ SAFE_BYTE_GET_AND_INC (segment_selector_size, start, 1, finish);
+ if (segment_selector_size != 0)
+ {
+ warn (_("The %s section contains "
+ "unsupported segment selector size: %d.\n"),
+ section->name, segment_selector_size);
+ return 0;
+ }
+
+ SAFE_BYTE_GET_AND_INC (offset_entry_count, start, 4, finish);
+ if (offset_entry_count != 0)
+ {
+ warn (_("The %s section contains "
+ "unsupported offset entry count: %u.\n"),
+ section->name, offset_entry_count);
+ return 0;
+ }
+ }
+
+ if (load_debug_info (file) == 0)
+ {
+ warn (_("Unable to load/parse the .debug_info section, so cannot interpret the %s section.\n"),
+ section->name);
+ return 0;
+ }
+
+ num_range_list = 0;
+ for (i = 0; i < num_debug_info_entries; i++)
+ num_range_list += debug_information [i].num_range_lists;
+
+ if (num_range_list == 0)
+ {
+ /* This can happen when the file was compiled with -gsplit-debug
+ which removes references to range lists from the primary .o file. */
+ printf (_("No range lists in .debug_info section.\n"));
+ return 1;
+ }
+
+ range_entries = (struct range_entry *)
+ xmalloc (sizeof (*range_entries) * num_range_list);
+ range_entry_fill = range_entries;
+
+ for (i = 0; i < num_debug_info_entries; i++)
+ {
+ debug_info *debug_info_p = &debug_information[i];
+ unsigned int j;
+
+ for (j = 0; j < debug_info_p->num_range_lists; j++)
+ {
+ range_entry_fill->ranges_offset = debug_info_p->range_lists[j];
+ range_entry_fill->debug_info_p = debug_info_p;
+ range_entry_fill++;
+ }
+ }
+
+ qsort (range_entries, num_range_list, sizeof (*range_entries),
+ range_entry_compar);
+
+ if (dwarf_check != 0 && range_entries[0].ranges_offset != 0)
+ warn (_("Range lists in %s section start at 0x%lx\n"),
+ section->name, (unsigned long) range_entries[0].ranges_offset);
+
+ introduce (section, FALSE);
+
+ printf (_(" Offset Begin End\n"));
+
+ for (i = 0; i < num_range_list; i++)
+ {
+ struct range_entry *range_entry = &range_entries[i];
+ debug_info *debug_info_p = range_entry->debug_info_p;
+ unsigned int pointer_size;
+ dwarf_vma offset;
+ unsigned char *next;
+ dwarf_vma base_address;
+
+ pointer_size = (is_rnglists ? address_size : debug_info_p->pointer_size);
+ offset = range_entry->ranges_offset;
+ next = section_begin + offset;
+ base_address = debug_info_p->base_address;
+
+ /* PR 17512: file: 001-101485-0.001:0.1. */
+ if (pointer_size < 2 || pointer_size > 8)
+ {
+ warn (_("Corrupt pointer size (%d) in debug entry at offset %8.8lx\n"),
+ pointer_size, (unsigned long) offset);
+ continue;
+ }
+
+ if (next < section_begin || next >= finish)
+ {
+ warn (_("Corrupt offset (%#8.8lx) in range entry %u\n"),
+ (unsigned long) offset, i);
+ continue;
+ }
+
+ if (dwarf_check != 0 && i > 0)
+ {
+ if (start < next)
+ warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"),
+ (unsigned long) (start - section_begin),
+ (unsigned long) (next - section_begin), section->name);
+ else if (start > next)
+ {
+ if (next == last_start)
+ continue;
+ warn (_("There is an overlap [0x%lx - 0x%lx] in %s section.\n"),
+ (unsigned long) (start - section_begin),
+ (unsigned long) (next - section_begin), section->name);
+ }
+ }
+
+ start = next;
+ last_start = next;
+
+ (is_rnglists ? display_debug_rnglists_list : display_debug_ranges_list)
+ (start, finish, pointer_size, offset, base_address);
+ }
+ putchar ('\n');
+
+ free (range_entries);
+
+ return 1;
+}
+
+typedef struct Frame_Chunk
+{
+ struct Frame_Chunk *next;
+ unsigned char *chunk_start;
+ unsigned int ncols;
+ /* DW_CFA_{undefined,same_value,offset,register,unreferenced} */
+ short int *col_type;
+ int *col_offset;
+ char *augmentation;
+ unsigned int code_factor;
+ int data_factor;
+ dwarf_vma pc_begin;
+ dwarf_vma pc_range;
+ unsigned int cfa_reg;
+ dwarf_vma cfa_offset;
+ unsigned int ra;
+ unsigned char fde_encoding;
+ unsigned char cfa_exp;
+ unsigned char ptr_size;
+ unsigned char segment_size;
+}
+Frame_Chunk;
+
+static const char *const *dwarf_regnames;
+static unsigned int dwarf_regnames_count;
+
+/* A marker for a col_type that means this column was never referenced
+ in the frame info. */
+#define DW_CFA_unreferenced (-1)
+
+/* Return 0 if no more space is needed, 1 if more space is needed,
+ -1 for invalid reg. */
+
+static int
+frame_need_space (Frame_Chunk *fc, unsigned int reg)
+{
+ unsigned int prev = fc->ncols;
+
+ if (reg < (unsigned int) fc->ncols)
+ return 0;
+
+ if (dwarf_regnames_count
+ && reg > dwarf_regnames_count)
+ return -1;
+
+ fc->ncols = reg + 1;
+ /* PR 17512: file: 10450-2643-0.004.
+ If reg == -1 then this can happen... */
+ if (fc->ncols == 0)
+ return -1;
+
+ /* PR 17512: file: 2844a11d. */
+ if (fc->ncols > 1024)
+ {
+ error (_("Unfeasibly large register number: %u\n"), reg);
+ fc->ncols = 0;
+ /* FIXME: 1024 is an arbitrary limit. Increase it if
+ we ever encounter a valid binary that exceeds it. */
+ return -1;
+ }
+
+ fc->col_type = (short int *) xcrealloc (fc->col_type, fc->ncols,
+ sizeof (short int));
+ fc->col_offset = (int *) xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
+ /* PR 17512: file:002-10025-0.005. */
+ if (fc->col_type == NULL || fc->col_offset == NULL)
+ {
+ error (_("Out of memory allocating %u columns in dwarf frame arrays\n"),
+ fc->ncols);
+ fc->ncols = 0;
+ return -1;
+ }
+
+ while (prev < fc->ncols)
+ {
+ fc->col_type[prev] = DW_CFA_unreferenced;
+ fc->col_offset[prev] = 0;
+ prev++;
+ }
+ return 1;
+}
+
+static const char *const dwarf_regnames_i386[] =
+{
+ "eax", "ecx", "edx", "ebx", /* 0 - 3 */
+ "esp", "ebp", "esi", "edi", /* 4 - 7 */
+ "eip", "eflags", NULL, /* 8 - 10 */
+ "st0", "st1", "st2", "st3", /* 11 - 14 */
+ "st4", "st5", "st6", "st7", /* 15 - 18 */
+ NULL, NULL, /* 19 - 20 */
+ "xmm0", "xmm1", "xmm2", "xmm3", /* 21 - 24 */
+ "xmm4", "xmm5", "xmm6", "xmm7", /* 25 - 28 */
+ "mm0", "mm1", "mm2", "mm3", /* 29 - 32 */
+ "mm4", "mm5", "mm6", "mm7", /* 33 - 36 */
+ "fcw", "fsw", "mxcsr", /* 37 - 39 */
+ "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL, /* 40 - 47 */
+ "tr", "ldtr", /* 48 - 49 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 50 - 57 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 58 - 65 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 66 - 73 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 74 - 81 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 82 - 89 */
+ NULL, NULL, NULL, /* 90 - 92 */
+ "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" /* 93 - 100 */
+};
+
+static const char *const dwarf_regnames_iamcu[] =
+{
+ "eax", "ecx", "edx", "ebx", /* 0 - 3 */
+ "esp", "ebp", "esi", "edi", /* 4 - 7 */
+ "eip", "eflags", NULL, /* 8 - 10 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 11 - 18 */
+ NULL, NULL, /* 19 - 20 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 21 - 28 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 29 - 36 */
+ NULL, NULL, NULL, /* 37 - 39 */
+ "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL, /* 40 - 47 */
+ "tr", "ldtr", /* 48 - 49 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 50 - 57 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 58 - 65 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 66 - 73 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 74 - 81 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 82 - 89 */
+ NULL, NULL, NULL, /* 90 - 92 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* 93 - 100 */
+};
+
+void
+init_dwarf_regnames_i386 (void)
+{
+ dwarf_regnames = dwarf_regnames_i386;
+ dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_i386);
+}
+
+void
+init_dwarf_regnames_iamcu (void)
+{
+ dwarf_regnames = dwarf_regnames_iamcu;
+ dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_iamcu);
+}
+
+static const char *const dwarf_regnames_x86_64[] =
+{
+ "rax", "rdx", "rcx", "rbx",
+ "rsi", "rdi", "rbp", "rsp",
+ "r8", "r9", "r10", "r11",
+ "r12", "r13", "r14", "r15",
+ "rip",
+ "xmm0", "xmm1", "xmm2", "xmm3",
+ "xmm4", "xmm5", "xmm6", "xmm7",
+ "xmm8", "xmm9", "xmm10", "xmm11",
+ "xmm12", "xmm13", "xmm14", "xmm15",
+ "st0", "st1", "st2", "st3",
+ "st4", "st5", "st6", "st7",
+ "mm0", "mm1", "mm2", "mm3",
+ "mm4", "mm5", "mm6", "mm7",
+ "rflags",
+ "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
+ "fs.base", "gs.base", NULL, NULL,
+ "tr", "ldtr",
+ "mxcsr", "fcw", "fsw",
+ "xmm16", "xmm17", "xmm18", "xmm19",
+ "xmm20", "xmm21", "xmm22", "xmm23",
+ "xmm24", "xmm25", "xmm26", "xmm27",
+ "xmm28", "xmm29", "xmm30", "xmm31",
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 83 - 90 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 91 - 98 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 99 - 106 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 107 - 114 */
+ NULL, NULL, NULL, /* 115 - 117 */
+ "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"
+};
+
+void
+init_dwarf_regnames_x86_64 (void)
+{
+ dwarf_regnames = dwarf_regnames_x86_64;
+ dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_x86_64);
+}
+
+static const char *const dwarf_regnames_aarch64[] =
+{
+ "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
+ "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
+ "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
+ "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp",
+ NULL, "elr", NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+};
+
+void
+init_dwarf_regnames_aarch64 (void)
+{
+ dwarf_regnames = dwarf_regnames_aarch64;
+ dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_aarch64);
+}
+
+static const char *const dwarf_regnames_s390[] =
+{
+ /* Avoid saying "r5 (r5)", so omit the names of r0-r15. */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "f0", "f2", "f4", "f6", "f1", "f3", "f5", "f7",
+ "f8", "f10", "f12", "f14", "f9", "f11", "f13", "f15",
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
+ "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
+ "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15",
+ "pswm", "pswa",
+ NULL, NULL,
+ "v16", "v18", "v20", "v22", "v17", "v19", "v21", "v23",
+ "v24", "v26", "v28", "v30", "v25", "v27", "v29", "v31",
+};
+
+void
+init_dwarf_regnames_s390 (void)
+{
+ dwarf_regnames = dwarf_regnames_s390;
+ dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_s390);
+}
+
+static const char *const dwarf_regnames_riscv[] =
+{
+ "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", /* 0 - 7 */
+ "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", /* 8 - 15 */
+ "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", /* 16 - 23 */
+ "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", /* 24 - 31 */
+ "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", /* 32 - 39 */
+ "fs0", "fs1", /* 40 - 41 */
+ "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7", /* 42 - 49 */
+ "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", /* 50 - 57 */
+ "fs10", "fs11", /* 58 - 59 */
+ "ft8", "ft9", "ft10", "ft11" /* 60 - 63 */
+};
+
+void
+init_dwarf_regnames_riscv (void)
+{
+ dwarf_regnames = dwarf_regnames_riscv;
+ dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_riscv);
+}
+
+void
+init_dwarf_regnames (unsigned int e_machine)
+{
+ switch (e_machine)
+ {
+ case EM_386:
+ init_dwarf_regnames_i386 ();
+ break;
+
+ case EM_IAMCU:
+ init_dwarf_regnames_iamcu ();
+ break;
+
+ case EM_X86_64:
+ case EM_L1OM:
+ case EM_K1OM:
+ init_dwarf_regnames_x86_64 ();
+ break;
+
+ case EM_AARCH64:
+ init_dwarf_regnames_aarch64 ();
+ break;
+
+ case EM_S390:
+ init_dwarf_regnames_s390 ();
+ break;
+
+ case EM_RISCV:
+ init_dwarf_regnames_riscv ();
+ break;
+
+ default:
+ break;
+ }
+}
+
+static const char *
+regname (unsigned int regno, int row)
+{
+ static char reg[64];
+
+ if (dwarf_regnames
+ && regno < dwarf_regnames_count
+ && dwarf_regnames [regno] != NULL)
+ {
+ if (row)
+ return dwarf_regnames [regno];
+ snprintf (reg, sizeof (reg), "r%d (%s)", regno,
+ dwarf_regnames [regno]);
+ }
+ else
+ snprintf (reg, sizeof (reg), "r%d", regno);
+ return reg;
+}
+
+static void
+frame_display_row (Frame_Chunk *fc, int *need_col_headers, unsigned int *max_regs)
+{
+ unsigned int r;
+ char tmp[100];
+
+ if (*max_regs != fc->ncols)
+ *max_regs = fc->ncols;
+
+ if (*need_col_headers)
+ {
+ static const char *sloc = " LOC";
+
+ *need_col_headers = 0;
+
+ printf ("%-*s CFA ", eh_addr_size * 2, sloc);
+
+ for (r = 0; r < *max_regs; r++)
+ if (fc->col_type[r] != DW_CFA_unreferenced)
+ {
+ if (r == fc->ra)
+ printf ("ra ");
+ else
+ printf ("%-5s ", regname (r, 1));
+ }
+
+ printf ("\n");
+ }
+
+ print_dwarf_vma (fc->pc_begin, eh_addr_size);
+ if (fc->cfa_exp)
+ strcpy (tmp, "exp");
+ else
+ sprintf (tmp, "%s%+d", regname (fc->cfa_reg, 1), (int) fc->cfa_offset);
+ printf ("%-8s ", tmp);
+
+ for (r = 0; r < fc->ncols; r++)
+ {
+ if (fc->col_type[r] != DW_CFA_unreferenced)
+ {
+ switch (fc->col_type[r])
+ {
+ case DW_CFA_undefined:
+ strcpy (tmp, "u");
+ break;
+ case DW_CFA_same_value:
+ strcpy (tmp, "s");
+ break;
+ case DW_CFA_offset:
+ sprintf (tmp, "c%+d", fc->col_offset[r]);
+ break;
+ case DW_CFA_val_offset:
+ sprintf (tmp, "v%+d", fc->col_offset[r]);
+ break;
+ case DW_CFA_register:
+ sprintf (tmp, "%s", regname (fc->col_offset[r], 0));
+ break;
+ case DW_CFA_expression:
+ strcpy (tmp, "exp");
+ break;
+ case DW_CFA_val_expression:
+ strcpy (tmp, "vexp");
+ break;
+ default:
+ strcpy (tmp, "n/a");
+ break;
+ }
+ printf ("%-5s ", tmp);
+ }
+ }
+ printf ("\n");
+}
+
+#define GET(VAR, N) SAFE_BYTE_GET_AND_INC (VAR, start, N, end)
+
+static unsigned char *
+read_cie (unsigned char *start, unsigned char *end,
+ Frame_Chunk **p_cie, int *p_version,
+ bfd_size_type *p_aug_len, unsigned char **p_aug)
+{
+ int version;
+ Frame_Chunk *fc;
+ unsigned int length_return;
+ unsigned char *augmentation_data = NULL;
+ bfd_size_type augmentation_data_len = 0;
+
+ * p_cie = NULL;
+ /* PR 17512: file: 001-228113-0.004. */
+ if (start >= end)
+ return end;
+
+ fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
+ memset (fc, 0, sizeof (Frame_Chunk));
+
+ fc->col_type = (short int *) xmalloc (sizeof (short int));
+ fc->col_offset = (int *) xmalloc (sizeof (int));
+
+ version = *start++;
+
+ fc->augmentation = (char *) start;
+ /* PR 17512: file: 001-228113-0.004.
+ Skip past augmentation name, but avoid running off the end of the data. */
+ while (start < end)
+ if (* start ++ == '\0')
+ break;
+ if (start == end)
+ {
+ warn (_("No terminator for augmentation name\n"));
+ goto fail;
+ }
+
+ if (strcmp (fc->augmentation, "eh") == 0)
+ start += eh_addr_size;
+
+ if (version >= 4)
+ {
+ GET (fc->ptr_size, 1);
+ if (fc->ptr_size < 1 || fc->ptr_size > 8)
+ {
+ warn (_("Invalid pointer size (%d) in CIE data\n"), fc->ptr_size);
+ goto fail;
+ }
+
+ GET (fc->segment_size, 1);
+ /* PR 17512: file: e99d2804. */
+ if (fc->segment_size > 8 || fc->segment_size + fc->ptr_size > 8)
+ {
+ warn (_("Invalid segment size (%d) in CIE data\n"), fc->segment_size);
+ goto fail;
+ }
+
+ eh_addr_size = fc->ptr_size;
+ }
+ else
+ {
+ fc->ptr_size = eh_addr_size;
+ fc->segment_size = 0;
+ }
+
+ READ_ULEB (fc->code_factor);
+ READ_SLEB (fc->data_factor);
+
+ if (version == 1)
+ {
+ GET (fc->ra, 1);
+ }
+ else
+ {
+ READ_ULEB (fc->ra);
+ }
+
+ if (fc->augmentation[0] == 'z')
+ {
+ READ_ULEB (augmentation_data_len);
+ augmentation_data = start;
+ /* PR 17512: file: 11042-2589-0.004. */
+ if (augmentation_data_len > (bfd_size_type) (end - start))
+ {
+ warn (_("Augmentation data too long: 0x%s, expected at most %#lx\n"),
+ dwarf_vmatoa ("x", augmentation_data_len),
+ (unsigned long) (end - start));
+ goto fail;
+ }
+ start += augmentation_data_len;
+ }
+
+ if (augmentation_data_len)
+ {
+ unsigned char *p;
+ unsigned char *q;
+ unsigned char *qend;
+
+ p = (unsigned char *) fc->augmentation + 1;
+ q = augmentation_data;
+ qend = q + augmentation_data_len;
+
+ while (p < end && q < qend)
+ {
+ if (*p == 'L')
+ q++;
+ else if (*p == 'P')
+ q += 1 + size_of_encoded_value (*q);
+ else if (*p == 'R')
+ fc->fde_encoding = *q++;
+ else if (*p == 'S')
+ ;
+ else
+ break;
+ p++;
+ }
+ /* Note - it is OK if this loop terminates with q < qend.
+ Padding may have been inserted to align the end of the CIE. */
+ }
+
+ *p_cie = fc;
+ if (p_version)
+ *p_version = version;
+ if (p_aug_len)
+ {
+ *p_aug_len = augmentation_data_len;
+ *p_aug = augmentation_data;
+ }
+ return start;
+
+ fail:
+ free (fc->col_offset);
+ free (fc->col_type);
+ free (fc);
+ return end;
+}
+
+/* Prints out the contents on the DATA array formatted as unsigned bytes.
+ If do_wide is not enabled, then formats the output to fit into 80 columns.
+ PRINTED contains the number of characters already written to the current
+ output line. */
+
+static void
+display_data (bfd_size_type printed,
+ const unsigned char * data,
+ const bfd_size_type len)
+{
+ if (do_wide || len < ((80 - printed) / 3))
+ for (printed = 0; printed < len; ++printed)
+ printf (" %02x", data[printed]);
+ else
+ {
+ for (printed = 0; printed < len; ++printed)
+ {
+ if (printed % (80 / 3) == 0)
+ putchar ('\n');
+ printf (" %02x", data[printed]);
+ }
+ }
+}
+
+/* Prints out the contents on the augmentation data array.
+ If do_wide is not enabled, then formats the output to fit into 80 columns. */
+
+static void
+display_augmentation_data (const unsigned char * data, const bfd_size_type len)
+{
+ bfd_size_type i;
+
+ i = printf (_(" Augmentation data: "));
+ display_data (i, data, len);
+}
+
+static int
+display_debug_frames (struct dwarf_section *section,
+ void *file ATTRIBUTE_UNUSED)
+{
+ unsigned char *start = section->start;
+ unsigned char *end = start + section->size;
+ unsigned char *section_start = start;
+ Frame_Chunk *chunks = NULL, *forward_refs = NULL;
+ Frame_Chunk *remembered_state = NULL;
+ Frame_Chunk *rs;
+ bfd_boolean is_eh = strcmp (section->name, ".eh_frame") == 0;
+ unsigned int length_return;
+ unsigned int max_regs = 0;
+ const char *bad_reg = _("bad register: ");
+ unsigned int saved_eh_addr_size = eh_addr_size;
+
+ introduce (section, FALSE);
+
+ while (start < end)
+ {
+ unsigned char *saved_start;
+ unsigned char *block_end;
+ dwarf_vma length;
+ dwarf_vma cie_id;
+ Frame_Chunk *fc;
+ Frame_Chunk *cie;
+ int need_col_headers = 1;
+ unsigned char *augmentation_data = NULL;
+ bfd_size_type augmentation_data_len = 0;
+ unsigned int encoded_ptr_size = saved_eh_addr_size;
+ unsigned int offset_size;
+ unsigned int initial_length_size;
+ bfd_boolean all_nops;
+
+ saved_start = start;
+
+ SAFE_BYTE_GET_AND_INC (length, start, 4, end);
+
+ if (length == 0)
+ {
+ printf ("\n%08lx ZERO terminator\n\n",
+ (unsigned long)(saved_start - section_start));
+ /* Skip any zero terminators that directly follow.
+ A corrupt section size could have loaded a whole
+ slew of zero filled memory bytes. eg
+ PR 17512: file: 070-19381-0.004. */
+ while (start < end && * start == 0)
+ ++ start;
+ continue;
+ }
+
+ if (length == 0xffffffff)
+ {
+ SAFE_BYTE_GET_AND_INC (length, start, 8, end);
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
+ }
+
+ block_end = saved_start + length + initial_length_size;
+ if (block_end > end || block_end < start)
+ {
+ warn ("Invalid length 0x%s in FDE at %#08lx\n",
+ dwarf_vmatoa_1 (NULL, length, offset_size),
+ (unsigned long) (saved_start - section_start));
+ block_end = end;
+ }
+
+ SAFE_BYTE_GET_AND_INC (cie_id, start, offset_size, end);
+
+ if (is_eh ? (cie_id == 0) : ((offset_size == 4 && cie_id == DW_CIE_ID)
+ || (offset_size == 8 && cie_id == DW64_CIE_ID)))
+ {
+ int version;
+ unsigned int mreg;
+
+ start = read_cie (start, end, &cie, &version,
+ &augmentation_data_len, &augmentation_data);
+ /* PR 17512: file: 027-135133-0.005. */
+ if (cie == NULL)
+ break;
+
+ fc = cie;
+ fc->next = chunks;
+ chunks = fc;
+ fc->chunk_start = saved_start;
+ mreg = max_regs > 0 ? max_regs - 1 : 0;
+ if (mreg < fc->ra)
+ mreg = fc->ra;
+ if (frame_need_space (fc, mreg) < 0)
+ break;
+ if (fc->fde_encoding)
+ encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
+
+ printf ("\n%08lx ", (unsigned long) (saved_start - section_start));
+ print_dwarf_vma (length, fc->ptr_size);
+ print_dwarf_vma (cie_id, offset_size);
+
+ if (do_debug_frames_interp)
+ {
+ printf ("CIE \"%s\" cf=%d df=%d ra=%d\n", fc->augmentation,
+ fc->code_factor, fc->data_factor, fc->ra);
+ }
+ else
+ {
+ printf ("CIE\n");
+ printf (" Version: %d\n", version);
+ printf (" Augmentation: \"%s\"\n", fc->augmentation);
+ if (version >= 4)
+ {
+ printf (" Pointer Size: %u\n", fc->ptr_size);
+ printf (" Segment Size: %u\n", fc->segment_size);
+ }
+ printf (" Code alignment factor: %u\n", fc->code_factor);
+ printf (" Data alignment factor: %d\n", fc->data_factor);
+ printf (" Return address column: %d\n", fc->ra);
+
+ if (augmentation_data_len)
+ display_augmentation_data (augmentation_data, augmentation_data_len);
+
+ putchar ('\n');
+ }
+ }
+ else
+ {
+ unsigned char *look_for;
+ static Frame_Chunk fde_fc;
+ unsigned long segment_selector;
+
+ if (is_eh)
+ {
+ dwarf_vma sign = (dwarf_vma) 1 << (offset_size * 8 - 1);
+ look_for = start - 4 - ((cie_id ^ sign) - sign);
+ }
+ else
+ look_for = section_start + cie_id;
+
+ if (look_for <= saved_start)
+ {
+ for (cie = chunks; cie ; cie = cie->next)
+ if (cie->chunk_start == look_for)
+ break;
+ }
+ else
+ {
+ for (cie = forward_refs; cie ; cie = cie->next)
+ if (cie->chunk_start == look_for)
+ break;
+ if (!cie)
+ {
+ unsigned int off_size;
+ unsigned char *cie_scan;
+
+ cie_scan = look_for;
+ off_size = 4;
+ SAFE_BYTE_GET_AND_INC (length, cie_scan, 4, end);
+ if (length == 0xffffffff)
+ {
+ SAFE_BYTE_GET_AND_INC (length, cie_scan, 8, end);
+ off_size = 8;
+ }
+ if (length != 0)
+ {
+ dwarf_vma c_id;
+
+ SAFE_BYTE_GET_AND_INC (c_id, cie_scan, off_size, end);
+ if (is_eh
+ ? c_id == 0
+ : ((off_size == 4 && c_id == DW_CIE_ID)
+ || (off_size == 8 && c_id == DW64_CIE_ID)))
+ {
+ int version;
+ unsigned int mreg;
+
+ read_cie (cie_scan, end, &cie, &version,
+ &augmentation_data_len, &augmentation_data);
+ /* PR 17512: file: 3450-2098-0.004. */
+ if (cie == NULL)
+ {
+ warn (_("Failed to read CIE information\n"));
+ break;
+ }
+ cie->next = forward_refs;
+ forward_refs = cie;
+ cie->chunk_start = look_for;
+ mreg = max_regs > 0 ? max_regs - 1 : 0;
+ if (mreg < cie->ra)
+ mreg = cie->ra;
+ if (frame_need_space (cie, mreg) < 0)
+ {
+ warn (_("Invalid max register\n"));
+ break;
+ }
+ if (cie->fde_encoding)
+ encoded_ptr_size
+ = size_of_encoded_value (cie->fde_encoding);
+ }
+ }
+ }
+ }
+
+ fc = &fde_fc;
+ memset (fc, 0, sizeof (Frame_Chunk));
+
+ if (!cie)
+ {
+ warn ("Invalid CIE pointer 0x%s in FDE at %#08lx\n",
+ dwarf_vmatoa_1 (NULL, cie_id, offset_size),
+ (unsigned long) (saved_start - section_start));
+ fc->ncols = 0;
+ fc->col_type = (short int *) xmalloc (sizeof (short int));
+ fc->col_offset = (int *) xmalloc (sizeof (int));
+ if (frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0) < 0)
+ {
+ warn (_("Invalid max register\n"));
+ break;
+ }
+ cie = fc;
+ fc->augmentation = "";
+ fc->fde_encoding = 0;
+ fc->ptr_size = eh_addr_size;
+ fc->segment_size = 0;
+ }
+ else
+ {
+ fc->ncols = cie->ncols;
+ fc->col_type = (short int *) xcmalloc (fc->ncols, sizeof (short int));
+ fc->col_offset = (int *) xcmalloc (fc->ncols, sizeof (int));
+ memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
+ memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
+ fc->augmentation = cie->augmentation;
+ fc->ptr_size = cie->ptr_size;
+ eh_addr_size = cie->ptr_size;
+ fc->segment_size = cie->segment_size;
+ fc->code_factor = cie->code_factor;
+ fc->data_factor = cie->data_factor;
+ fc->cfa_reg = cie->cfa_reg;
+ fc->cfa_offset = cie->cfa_offset;
+ fc->ra = cie->ra;
+ if (frame_need_space (fc, max_regs > 0 ? max_regs - 1: 0) < 0)
+ {
+ warn (_("Invalid max register\n"));
+ break;
+ }
+ fc->fde_encoding = cie->fde_encoding;
+ }
+
+ if (fc->fde_encoding)
+ encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
+
+ segment_selector = 0;
+ if (fc->segment_size)
+ {
+ if (fc->segment_size > sizeof (segment_selector))
+ {
+ /* PR 17512: file: 9e196b3e. */
+ warn (_("Probably corrupt segment size: %d - using 4 instead\n"), fc->segment_size);
+ fc->segment_size = 4;
+ }
+ SAFE_BYTE_GET_AND_INC (segment_selector, start, fc->segment_size, end);
+ }
+
+ fc->pc_begin = get_encoded_value (&start, fc->fde_encoding, section, end);
+
+ /* FIXME: It appears that sometimes the final pc_range value is
+ encoded in less than encoded_ptr_size bytes. See the x86_64
+ run of the "objcopy on compressed debug sections" test for an
+ example of this. */
+ SAFE_BYTE_GET_AND_INC (fc->pc_range, start, encoded_ptr_size, end);
+
+ if (cie->augmentation[0] == 'z')
+ {
+ READ_ULEB (augmentation_data_len);
+ augmentation_data = start;
+ start += augmentation_data_len;
+ /* PR 17512 file: 722-8446-0.004 and PR 22386. */
+ if (start >= end
+ || ((bfd_signed_vma) augmentation_data_len) < 0
+ || augmentation_data > start)
+ {
+ warn (_("Corrupt augmentation data length: 0x%s\n"),
+ dwarf_vmatoa ("x", augmentation_data_len));
+ start = end;
+ augmentation_data = NULL;
+ augmentation_data_len = 0;
+ }
+ }
+
+ printf ("\n%08lx %s %s FDE cie=%08lx pc=",
+ (unsigned long)(saved_start - section_start),
+ dwarf_vmatoa_1 (NULL, length, fc->ptr_size),
+ dwarf_vmatoa_1 (NULL, cie_id, offset_size),
+ (unsigned long)(cie->chunk_start - section_start));
+
+ if (fc->segment_size)
+ printf ("%04lx:", segment_selector);
+
+ printf ("%s..%s\n",
+ dwarf_vmatoa_1 (NULL, fc->pc_begin, fc->ptr_size),
+ dwarf_vmatoa_1 (NULL, fc->pc_begin + fc->pc_range, fc->ptr_size));
+
+ if (! do_debug_frames_interp && augmentation_data_len)
+ {
+ display_augmentation_data (augmentation_data, augmentation_data_len);
+ putchar ('\n');
+ }
+ }
+
+ /* At this point, fc is the current chunk, cie (if any) is set, and
+ we're about to interpret instructions for the chunk. */
+ /* ??? At present we need to do this always, since this sizes the
+ fc->col_type and fc->col_offset arrays, which we write into always.
+ We should probably split the interpreted and non-interpreted bits
+ into two different routines, since there's so much that doesn't
+ really overlap between them. */
+ if (1 || do_debug_frames_interp)
+ {
+ /* Start by making a pass over the chunk, allocating storage
+ and taking note of what registers are used. */
+ unsigned char *tmp = start;
+
+ while (start < block_end)
+ {
+ unsigned int reg, op, opa;
+ unsigned long temp;
+ unsigned char * new_start;
+
+ op = *start++;
+ opa = op & 0x3f;
+ if (op & 0xc0)
+ op &= 0xc0;
+
+ /* Warning: if you add any more cases to this switch, be
+ sure to add them to the corresponding switch below. */
+ switch (op)
+ {
+ case DW_CFA_advance_loc:
+ break;
+ case DW_CFA_offset:
+ SKIP_ULEB ();
+ if (frame_need_space (fc, opa) >= 0)
+ fc->col_type[opa] = DW_CFA_undefined;
+ break;
+ case DW_CFA_restore:
+ if (frame_need_space (fc, opa) >= 0)
+ fc->col_type[opa] = DW_CFA_undefined;
+ break;
+ case DW_CFA_set_loc:
+ start += encoded_ptr_size;
+ break;
+ case DW_CFA_advance_loc1:
+ start += 1;
+ break;
+ case DW_CFA_advance_loc2:
+ start += 2;
+ break;
+ case DW_CFA_advance_loc4:
+ start += 4;
+ break;
+ case DW_CFA_offset_extended:
+ case DW_CFA_val_offset:
+ READ_ULEB (reg);
+ SKIP_ULEB ();
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_restore_extended:
+ READ_ULEB (reg);
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_undefined:
+ READ_ULEB (reg);
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_same_value:
+ READ_ULEB (reg);
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_register:
+ READ_ULEB (reg);
+ SKIP_ULEB ();
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_def_cfa:
+ SKIP_ULEB ();
+ SKIP_ULEB ();
+ break;
+ case DW_CFA_def_cfa_register:
+ SKIP_ULEB ();
+ break;
+ case DW_CFA_def_cfa_offset:
+ SKIP_ULEB ();
+ break;
+ case DW_CFA_def_cfa_expression:
+ READ_ULEB (temp);
+ new_start = start + temp;
+ if (new_start < start)
+ {
+ warn (_("Corrupt CFA_def expression value: %lu\n"), temp);
+ start = block_end;
+ }
+ else
+ start = new_start;
+ break;
+ case DW_CFA_expression:
+ case DW_CFA_val_expression:
+ READ_ULEB (reg);
+ READ_ULEB (temp);
+ new_start = start + temp;
+ if (new_start < start)
+ {
+ /* PR 17512: file:306-192417-0.005. */
+ warn (_("Corrupt CFA expression value: %lu\n"), temp);
+ start = block_end;
+ }
+ else
+ start = new_start;
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_offset_extended_sf:
+ case DW_CFA_val_offset_sf:
+ READ_ULEB (reg);
+ SKIP_SLEB ();
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_def_cfa_sf:
+ SKIP_ULEB ();
+ SKIP_SLEB ();
+ break;
+ case DW_CFA_def_cfa_offset_sf:
+ SKIP_SLEB ();
+ break;
+ case DW_CFA_MIPS_advance_loc8:
+ start += 8;
+ break;
+ case DW_CFA_GNU_args_size:
+ SKIP_ULEB ();
+ break;
+ case DW_CFA_GNU_negative_offset_extended:
+ READ_ULEB (reg);
+ SKIP_ULEB ();
+ if (frame_need_space (fc, reg) >= 0)
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ default:
+ break;
+ }
+ }
+ start = tmp;
+ }
+
+ all_nops = TRUE;
+
+ /* Now we know what registers are used, make a second pass over
+ the chunk, this time actually printing out the info. */
+
+ while (start < block_end)
+ {
+ unsigned char * tmp;
+ unsigned op, opa;
+ unsigned long ul, roffs;
+ /* Note: It is tempting to use an unsigned long for 'reg' but there
+ are various functions, notably frame_space_needed() that assume that
+ reg is an unsigned int. */
+ unsigned int reg;
+ dwarf_signed_vma l;
+ dwarf_vma ofs;