#include "dwarf.h"
#include "gdb/gdb-index.h"
#include "filenames.h"
+#include "safe-ctype.h"
#include <assert.h>
#undef MAX
#define MIN(a, b) ((a) < (b) ? (a) : (b))
static const char *regname (unsigned int regno, int row);
+static const char *regname_internal_by_table_only (unsigned int regno);
static int have_frame_base;
static int need_base_address;
struct cu_tu_set
{
- uint64_t signature;
- dwarf_vma section_offsets[DW_SECT_MAX];
- size_t section_sizes[DW_SECT_MAX];
+ uint64_t signature;
+ dwarf_vma section_offsets[DW_SECT_MAX];
+ size_t section_sizes[DW_SECT_MAX];
};
static int cu_count = 0;
static bfd_boolean load_cu_tu_indexes (void *);
+/* An array that indicates for a given level of CU nesting whether
+ the latest DW_AT_type seen for that level was a signed type or
+ an unsigned type. */
+#define MAX_CU_NESTING (1 << 8)
+static bfd_boolean level_type_signed[MAX_CU_NESTING];
+
/* Values for do_debug_lines. */
#define FLAG_DEBUG_LINES_RAW 1
#define FLAG_DEBUG_LINES_DECODED 2
first_dwo_info = NULL;
}
+/* Ensure that START + UVALUE is less than END.
+ Return an adjusted UVALUE if necessary to ensure this relationship. */
+
+static inline dwarf_vma
+check_uvalue (const unsigned char * start,
+ dwarf_vma uvalue,
+ const unsigned char * end)
+{
+ dwarf_vma max_uvalue = end - start;
+
+ /* See PR 17512: file: 008-103549-0.001:0.1.
+ and PR 24829 for examples of where these tests are triggered. */
+ if (uvalue > max_uvalue)
+ {
+ warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
+ uvalue = max_uvalue;
+ }
+
+ return uvalue;
+}
+
+static unsigned char *
+skip_attr_bytes (unsigned long form,
+ unsigned char * data,
+ unsigned const char * end,
+ dwarf_vma pointer_size,
+ dwarf_vma offset_size,
+ int dwarf_version,
+ dwarf_vma * value_return)
+{
+ unsigned int bytes_read;
+ dwarf_vma uvalue = 0;
+
+ * value_return = 0;
+
+ switch (form)
+ {
+ case DW_FORM_ref_addr:
+ if (dwarf_version == 2)
+ SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+ else if (dwarf_version == 3 || dwarf_version == 4)
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ else
+ return NULL;
+ break;
+
+ case DW_FORM_addr:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
+ break;
+
+ case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ case DW_FORM_sec_offset:
+ case DW_FORM_GNU_ref_alt:
+ case DW_FORM_GNU_strp_alt:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ break;
+
+ case DW_FORM_flag_present:
+ uvalue = 1;
+ break;
+
+ case DW_FORM_ref1:
+ case DW_FORM_flag:
+ case DW_FORM_data1:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+ break;
+
+ case DW_FORM_ref2:
+ case DW_FORM_data2:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
+ break;
+
+ case DW_FORM_ref4:
+ case DW_FORM_data4:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
+ break;
+
+ case DW_FORM_sdata:
+ uvalue = read_sleb128 (data, & bytes_read, end);
+ data += bytes_read;
+ break;
+
+ case DW_FORM_ref_udata:
+ case DW_FORM_udata:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_GNU_addr_index:
+ uvalue = read_uleb128 (data, & bytes_read, end);
+ data += bytes_read;
+ break;
+
+ case DW_FORM_ref8:
+ case DW_FORM_data8:
+ data += 8;
+ break;
+
+ case DW_FORM_data16:
+ data += 16;
+ break;
+
+ case DW_FORM_string:
+ data += strnlen ((char *) data, end - data) + 1;
+ break;
+
+ case DW_FORM_block:
+ case DW_FORM_exprloc:
+ uvalue = read_uleb128 (data, & bytes_read, end);
+ data += bytes_read + uvalue;
+ break;
+
+ case DW_FORM_block1:
+ SAFE_BYTE_GET (uvalue, data, 1, end);
+ data += 1 + uvalue;
+ break;
+
+ case DW_FORM_block2:
+ SAFE_BYTE_GET (uvalue, data, 2, end);
+ data += 2 + uvalue;
+ break;
+
+ case DW_FORM_block4:
+ SAFE_BYTE_GET (uvalue, data, 4, end);
+ data += 4 + uvalue;
+ break;
+
+ case DW_FORM_ref_sig8:
+ data += 8;
+ break;
+
+ case DW_FORM_indirect:
+ /* FIXME: Handle this form. */
+ default:
+ return NULL;
+ }
+
+ * value_return = uvalue;
+ if (data > end)
+ data = (unsigned char *) end;
+ return data;
+}
+
+/* Return IS_SIGNED set to TRUE if the type at
+ DATA can be determined to be a signed type. */
+
+static void
+get_type_signedness (unsigned char * start,
+ unsigned char * data,
+ unsigned const char * end,
+ dwarf_vma pointer_size,
+ dwarf_vma offset_size,
+ int dwarf_version,
+ bfd_boolean * is_signed,
+ bfd_boolean is_nested)
+{
+ unsigned long abbrev_number;
+ unsigned int bytes_read;
+ abbrev_entry * entry;
+ abbrev_attr * attr;
+
+ * is_signed = FALSE;
+
+ abbrev_number = read_uleb128 (data, & bytes_read, end);
+ data += bytes_read;
+
+ for (entry = first_abbrev;
+ entry != NULL && entry->entry != abbrev_number;
+ entry = entry->next)
+ continue;
+
+ if (entry == NULL)
+ /* FIXME: Issue a warning ? */
+ return;
+
+ for (attr = entry->first_attr;
+ attr != NULL && attr->attribute;
+ attr = attr->next)
+ {
+ dwarf_vma uvalue = 0;
+
+ data = skip_attr_bytes (attr->form, data, end, pointer_size,
+ offset_size, dwarf_version, & uvalue);
+ if (data == NULL)
+ return;
+
+ switch (attr->attribute)
+ {
+#if 0 /* FIXME: It would be nice to print the name of the type,
+ but this would mean updating a lot of binutils tests. */
+ case DW_AT_name:
+ if (attr->form == DW_FORM_strp)
+ printf ("%s", fetch_indirect_string (uvalue));
+ break;
+#endif
+ case DW_AT_type:
+ /* Recurse. */
+ if (is_nested)
+ {
+ /* FIXME: Warn - or is this expected ?
+ NB/ We need to avoid infinite recursion. */
+ return;
+ }
+ if (uvalue >= (size_t) (end - start))
+ return;
+ get_type_signedness (start, start + uvalue, end, pointer_size,
+ offset_size, dwarf_version, is_signed, TRUE);
+ break;
+
+ case DW_AT_encoding:
+ /* Determine signness. */
+ switch (uvalue)
+ {
+ case DW_ATE_address:
+ /* FIXME - some architectures have signed addresses. */
+ case DW_ATE_boolean:
+ case DW_ATE_unsigned:
+ case DW_ATE_unsigned_char:
+ case DW_ATE_unsigned_fixed:
+ * is_signed = FALSE;
+ break;
+
+ default:
+ case DW_ATE_complex_float:
+ case DW_ATE_float:
+ case DW_ATE_signed:
+ case DW_ATE_signed_char:
+ case DW_ATE_imaginary_float:
+ case DW_ATE_decimal_float:
+ case DW_ATE_signed_fixed:
+ * is_signed = TRUE;
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static void
+read_and_print_leb128 (unsigned char * data,
+ unsigned int * bytes_read,
+ unsigned const char * end,
+ bfd_boolean is_signed)
+{
+ if (is_signed)
+ {
+ dwarf_signed_vma sval = read_sleb128 (data, bytes_read, end);
+ printf ("%ld", (long) sval);
+ }
+ else
+ {
+ dwarf_vma uval = read_uleb128 (data, bytes_read, end);
+ printf ("%lu", (unsigned long) uval);
+ }
+}
+
+static void
+display_discr_list (unsigned long form,
+ dwarf_vma uvalue,
+ unsigned char * data,
+ unsigned const char * end,
+ int level)
+{
+ if (uvalue == 0)
+ {
+ printf ("[default]");
+ return;
+ }
+
+ switch (form)
+ {
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ /* Move data pointer back to the start of the byte array. */
+ data -= uvalue;
+ break;
+ default:
+ printf ("<corrupt>\n");
+ warn (_("corrupt discr_list - not using a block form\n"));
+ return;
+ }
+
+ if (uvalue < 2)
+ {
+ printf ("<corrupt>\n");
+ warn (_("corrupt discr_list - block not long enough\n"));
+ return;
+ }
+
+ bfd_boolean is_signed =
+ (level > 0 && level <= MAX_CU_NESTING)
+ ? level_type_signed [level - 1] : FALSE;
+
+ printf ("(");
+ while (uvalue)
+ {
+ unsigned char discriminant;
+ unsigned int bytes_read;
+
+ SAFE_BYTE_GET (discriminant, data, 1, end);
+ -- uvalue;
+ data ++;
+
+ assert (uvalue > 0);
+ switch (discriminant)
+ {
+ case DW_DSC_label:
+ printf ("label ");
+ read_and_print_leb128 (data, & bytes_read, end, is_signed);
+ assert (bytes_read <= uvalue && bytes_read > 0);
+ uvalue -= bytes_read;
+ data += bytes_read;
+ break;
+
+ case DW_DSC_range:
+ printf ("range ");
+ read_and_print_leb128 (data, & bytes_read, end, is_signed);
+ assert (bytes_read <= uvalue && bytes_read > 0);
+ uvalue -= bytes_read;
+ data += bytes_read;
+
+ printf ("..");
+ read_and_print_leb128 (data, & bytes_read, end, is_signed);
+ assert (bytes_read <= uvalue && bytes_read > 0);
+ uvalue -= bytes_read;
+ data += bytes_read;
+ break;
+
+ default:
+ printf ("<corrupt>\n");
+ warn (_("corrupt discr_list - unrecognised discriminant byte %#x\n"),
+ discriminant);
+ return;
+ }
+
+ if (uvalue)
+ printf (", ");
+ }
+
+ if (is_signed)
+ printf (")(signed)");
+ else
+ printf (")(unsigned)");
+}
+
static unsigned char *
read_and_display_attr_value (unsigned long attribute,
unsigned long form,
dwarf_signed_vma implicit_const,
+ unsigned char * start,
unsigned char * data,
unsigned char * end,
dwarf_vma cu_offset,
int do_loc,
struct dwarf_section * section,
struct cu_tu_set * this_set,
- char delimiter)
+ char delimiter,
+ int level)
{
- dwarf_vma uvalue = 0;
- unsigned char *block_start = NULL;
- unsigned char * orig_data = data;
- unsigned int bytes_read;
+ dwarf_vma uvalue = 0;
+ unsigned char * block_start = NULL;
+ unsigned char * orig_data = data;
+ unsigned int bytes_read;
if (data > end || (data == end && form != DW_FORM_flag_present))
{
implicit_const = read_sleb128 (data, & bytes_read, end);
data += bytes_read;
}
- return read_and_display_attr_value (attribute, form, implicit_const, data,
- end, cu_offset, pointer_size,
+ return read_and_display_attr_value (attribute, form, implicit_const,
+ start, data, end,
+ cu_offset, pointer_size,
offset_size, dwarf_version,
debug_info_p, do_loc,
- section, this_set, delimiter);
+ section, this_set, delimiter, level);
case DW_FORM_GNU_addr_index:
uvalue = read_uleb128 (data, & bytes_read, end);
data += bytes_read;
uvalue = 0;
block_start = end;
}
- /* FIXME: Testing "(block_start + uvalue) < block_start" miscompiles with
- gcc 4.8.3 running on an x86_64 host in 32-bit mode. So we pre-compute
- block_start + uvalue here. */
- data = block_start + uvalue;
- /* PR 17512: file: 008-103549-0.001:0.1. */
- if (block_start + uvalue > end || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
+
+ uvalue = check_uvalue (block_start, uvalue, end);
+
if (do_loc)
data = block_start + uvalue;
else
uvalue = 0;
block_start = end;
}
- data = block_start + uvalue;
- if (block_start + uvalue > end || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
+
+ uvalue = check_uvalue (block_start, uvalue, end);
+
if (do_loc)
data = block_start + uvalue;
else
uvalue = 0;
block_start = end;
}
- data = block_start + uvalue;
- if (block_start + uvalue > end || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
+
+ uvalue = check_uvalue (block_start, uvalue, end);
+
if (do_loc)
data = block_start + uvalue;
else
uvalue = 0;
block_start = end;
}
- data = block_start + uvalue;
- if (block_start + uvalue > end
- /* PR 17531: file: 5b5f0592. */
- || data < block_start)
- {
- warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
- uvalue = end - block_start;
- }
+
+ uvalue = check_uvalue (block_start, uvalue, end);
+
if (do_loc)
data = block_start + uvalue;
else
/* For some attributes we can display further information. */
switch (attribute)
{
+ case DW_AT_type:
+ if (level >= 0 && level < MAX_CU_NESTING
+ && uvalue < (size_t) (end - start))
+ {
+ bfd_boolean is_signed = FALSE;
+
+ get_type_signedness (start, start + uvalue, end, pointer_size,
+ offset_size, dwarf_version, & is_signed, FALSE);
+ level_type_signed[level] = is_signed;
+ }
+ break;
+
case DW_AT_inline:
printf ("\t");
switch (uvalue)
case DW_AT_discr_list:
printf ("\t");
- switch (uvalue)
- {
- case DW_DSC_label: printf (_("(label)")); break;
- case DW_DSC_range: printf (_("(range)")); break;
- default: printf (_("(unrecognised)")); break;
- }
+ display_discr_list (form, uvalue, data, end, level);
break;
case DW_AT_frame_base:
read_and_display_attr (unsigned long attribute,
unsigned long form,
dwarf_signed_vma implicit_const,
+ unsigned char * start,
unsigned char * data,
unsigned char * end,
dwarf_vma cu_offset,
debug_info * debug_info_p,
int do_loc,
struct dwarf_section * section,
- struct cu_tu_set * this_set)
+ struct cu_tu_set * this_set,
+ int level)
{
if (!do_loc)
printf (" %-18s:", get_AT_name (attribute));
- data = read_and_display_attr_value (attribute, form, implicit_const, data, end,
+ data = read_and_display_attr_value (attribute, form, implicit_const,
+ start, data, end,
cu_offset, pointer_size, offset_size,
dwarf_version, debug_info_p,
- do_loc, section, this_set, ' ');
+ do_loc, section, this_set, ' ', level);
if (!do_loc)
printf ("\n");
return data;
if (! do_loc && do_printing)
/* Show the offset from where the tag was extracted. */
printf (" <%lx>", (unsigned long)(tags - section_begin));
-
tags = read_and_display_attr (attr->attribute,
attr->form,
attr->implicit_const,
+ section_begin,
tags,
end,
cu_offset,
debug_info_p,
do_loc || ! do_printing,
section,
- this_set);
+ this_set,
+ level);
}
/* If a locview attribute appears before a location one,
format += bytes_read;
form = read_uleb128 (format, & bytes_read, end);
format += bytes_read;
- data = read_and_display_attr_value (0, form, 0, data, end, 0, 0,
+ data = read_and_display_attr_value (0, form, 0, start, data, end, 0, 0,
linfo->li_offset_size,
linfo->li_version, NULL,
((content_type == DW_LNCT_path) != (namepass == 1)),
- section, NULL, '\t');
+ section, NULL, '\t', -1);
}
}
if (data == end)
static int
display_debug_lines_decoded (struct dwarf_section * section,
+ unsigned char * start,
unsigned char * data,
unsigned char * end,
void * fileptr)
}
break;
}
- data = read_and_display_attr_value (0, form, 0, data, end,
+ data = read_and_display_attr_value (0, form, 0, start, data, end,
0, 0,
linfo.li_offset_size,
linfo.li_version,
NULL, 1, section,
- NULL, '\t');
+ NULL, '\t', -1);
}
if (data == end)
{
}
break;
}
- data = read_and_display_attr_value (0, form, 0, data, end,
+ data = read_and_display_attr_value (0, form, 0, start, data, end,
0, 0,
linfo.li_offset_size,
linfo.li_version,
NULL, 1, section,
- NULL, '\t');
+ NULL, '\t', -1);
}
if (data == end)
{
retValRaw = display_debug_lines_raw (section, data, end, file);
if (do_debug_lines & FLAG_DEBUG_LINES_DECODED)
- retValDecoded = display_debug_lines_decoded (section, data, end, file);
+ retValDecoded = display_debug_lines_decoded (section, data, data, end, file);
if (!retValRaw || !retValDecoded)
return 0;
SAFE_BYTE_GET_AND_INC (val, desc, 1, end);
curr
= read_and_display_attr_value (0, val, 0,
- curr, end, 0, 0, offset_size,
+ start, curr, end, 0, 0, offset_size,
version, NULL, 0, NULL,
- NULL, ' ');
+ NULL, ' ', -1);
if (n != nargs - 1)
printf (",");
}
static int
comp_addr_base (const void * v0, const void * v1)
{
- debug_info * info0 = (debug_info *) v0;
- debug_info * info1 = (debug_info *) v1;
+ debug_info *info0 = *(debug_info **) v0;
+ debug_info *info1 = *(debug_info **) v1;
return info0->addr_base - info1->addr_base;
}
}
Frame_Chunk;
+typedef const char *(*dwarf_regname_lookup_ftype) (unsigned int);
+static dwarf_regname_lookup_ftype dwarf_regnames_lookup_func;
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)
if (reg < (unsigned int) fc->ncols)
return 0;
- if (dwarf_regnames_count
+ if (dwarf_regnames_count > 0
&& reg > dwarf_regnames_count)
return -1;
return -1;
/* PR 17512: file: 2844a11d. */
- if (fc->ncols > 1024)
+ if (fc->ncols > 1024 && dwarf_regnames_count == 0)
{
error (_("Unfeasibly large register number: %u\n"), reg);
fc->ncols = 0;
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* 93 - 100 */
};
-void
+static void
init_dwarf_regnames_i386 (void)
{
dwarf_regnames = dwarf_regnames_i386;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_i386);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
-void
+static void
init_dwarf_regnames_iamcu (void)
{
dwarf_regnames = dwarf_regnames_iamcu;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_iamcu);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_x86_64[] =
"k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"
};
-void
+static void
init_dwarf_regnames_x86_64 (void)
{
dwarf_regnames = dwarf_regnames_x86_64;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_x86_64);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_aarch64[] =
"z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
};
-void
+static void
init_dwarf_regnames_aarch64 (void)
{
dwarf_regnames = dwarf_regnames_aarch64;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_aarch64);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_s390[] =
"v24", "v26", "v28", "v30", "v25", "v27", "v29", "v31",
};
-void
+static void
init_dwarf_regnames_s390 (void)
{
dwarf_regnames = dwarf_regnames_s390;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_s390);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_riscv[] =
"ft8", "ft9", "ft10", "ft11" /* 60 - 63 */
};
-void
+/* A RISC-V replacement for REGNAME_INTERNAL_BY_TABLE_ONLY which handles
+ the large number of CSRs. */
+
+static const char *
+regname_internal_riscv (unsigned int regno)
+{
+ const char *name = NULL;
+
+ /* Lookup in the table first, this covers GPR and FPR. */
+ if (regno < ARRAY_SIZE (dwarf_regnames_riscv))
+ name = dwarf_regnames_riscv [regno];
+ else if (regno >= 4096 && regno <= 8191)
+ {
+ /* This might be a CSR, these live in a sparse number space from 4096
+ to 8191 These numbers are defined in the RISC-V ELF ABI
+ document. */
+ switch (regno)
+ {
+#define DECLARE_CSR(NAME,VALUE) case VALUE + 4096: name = #NAME; break;
+#include "opcode/riscv-opc.h"
+#undef DECLARE_CSR
+
+ default:
+ {
+ static char csr_name[10];
+ snprintf (csr_name, sizeof (csr_name), "csr%d", (regno - 4096));
+ name = csr_name;
+ }
+ break;
+ }
+ }
+
+ return name;
+}
+
+static void
init_dwarf_regnames_riscv (void)
{
- dwarf_regnames = dwarf_regnames_riscv;
- dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_riscv);
+ dwarf_regnames = NULL;
+ dwarf_regnames_count = 8192;
+ dwarf_regnames_lookup_func = regname_internal_riscv;
}
void
-init_dwarf_regnames (unsigned int e_machine)
+init_dwarf_regnames_by_elf_machine_code (unsigned int e_machine)
{
+ dwarf_regnames_lookup_func = NULL;
+
switch (e_machine)
{
case EM_386:
}
}
-static const char *
-regname (unsigned int regno, int row)
+/* Initialize the DWARF register name lookup state based on the
+ architecture and specific machine type of a BFD. */
+
+void
+init_dwarf_regnames_by_bfd_arch_and_mach (enum bfd_architecture arch,
+ unsigned long mach)
{
- static char reg[64];
+ dwarf_regnames_lookup_func = NULL;
+
+ switch (arch)
+ {
+ case bfd_arch_i386:
+ switch (mach)
+ {
+ 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;
+
+ default:
+ break;
+ }
+}
- if (dwarf_regnames
+static const char *
+regname_internal_by_table_only (unsigned int regno)
+{
+ if (dwarf_regnames != NULL
&& regno < dwarf_regnames_count
&& dwarf_regnames [regno] != NULL)
+ return dwarf_regnames [regno];
+
+ return NULL;
+}
+
+static const char *
+regname (unsigned int regno, int name_only_p)
+{
+ static char reg[64];
+
+ const char *name = NULL;
+
+ if (dwarf_regnames_lookup_func != NULL)
+ name = dwarf_regnames_lookup_func (regno);
+
+ if (name != NULL)
{
- if (row)
- return dwarf_regnames [regno];
- snprintf (reg, sizeof (reg), "r%d (%s)", regno,
- dwarf_regnames [regno]);
+ if (name_only_p)
+ return name;
+ snprintf (reg, sizeof (reg), "r%d (%s)", regno, name);
}
else
snprintf (reg, sizeof (reg), "r%d", regno);
{
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)
+ if (augmentation_data_len > (bfd_size_type) (end - start))
{
- warn (_("Corrupt augmentation data length: 0x%s\n"),
- dwarf_vmatoa ("x", augmentation_data_len));
+ warn (_("Augmentation data too long: 0x%s, "
+ "expected at most %#lx\n"),
+ dwarf_vmatoa ("x", augmentation_data_len),
+ (unsigned long) (end - start));
start = end;
augmentation_data = NULL;
augmentation_data_len = 0;
}
+ start += augmentation_data_len;
}
printf ("\n%08lx %s %s FDE cie=%08lx pc=",
uint32_t augmentation_string_size;
unsigned int i;
unsigned long sec_off;
+ bfd_boolean augmentation_printable;
+ const char *augmentation_string;
unit_start = hdrptr;
augmentation_string_size);
augmentation_string_size += (-augmentation_string_size) & 3;
}
+
printf (_("Augmentation string:"));
+
+ augmentation_printable = TRUE;
+ augmentation_string = (const char *) hdrptr;
+
for (i = 0; i < augmentation_string_size; i++)
{
unsigned char uc;
SAFE_BYTE_GET_AND_INC (uc, hdrptr, 1, unit_end);
printf (" %02x", uc);
+
+ if (uc != 0 && !ISPRINT (uc))
+ augmentation_printable = FALSE;
+ }
+
+ if (augmentation_printable)
+ {
+ printf (" (\"");
+ for (i = 0;
+ i < augmentation_string_size && augmentation_string[i];
+ ++i)
+ putchar (augmentation_string[i]);
+ printf ("\")");
}
- putchar ('\n');
putchar ('\n');
printf (_("CU table:\n"));
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,
+ entryptr = read_and_display_attr_value (0, form, 0,
+ unit_start, entryptr, unit_end,
+ 0, 0, offset_size,
dwarf_version, NULL,
(tagno < 0), NULL,
- NULL, '=');
+ NULL, '=', -1);
}
++tagno;
}
SAFE_BYTE_GET (nslots, phdr + 12, 4, limit);
phash = phdr + 16;
- pindex = phash + nslots * 8;
- ppool = pindex + nslots * 4;
-
- /* PR 17531: file: 45d69832. */
- if (pindex < phash || ppool < phdr || (pindex == phash && nslots != 0))
- {
- warn (ngettext ("Section %s is too small for %d slot\n",
- "Section %s is too small for %d slots\n",
- nslots),
- section->name, nslots);
- return 0;
- }
+ pindex = phash + (size_t) nslots * 8;
+ ppool = pindex + (size_t) nslots * 4;
if (do_display)
{
introduce (section, FALSE);
- printf (_(" Version: %d\n"), version);
+ printf (_(" Version: %u\n"), version);
if (version >= 2)
- printf (_(" Number of columns: %d\n"), ncols);
- printf (_(" Number of used entries: %d\n"), nused);
- printf (_(" Number of slots: %d\n\n"), nslots);
+ printf (_(" Number of columns: %u\n"), ncols);
+ printf (_(" Number of used entries: %u\n"), nused);
+ printf (_(" Number of slots: %u\n\n"), nslots);
}
- if (ppool > limit || ppool < phdr)
+ /* PR 17531: file: 45d69832. */
+ if ((size_t) nslots * 8 / 8 != nslots
+ || phash < phdr || phash > limit
+ || pindex < phash || pindex > limit
+ || ppool < pindex || ppool > limit)
{
- warn (_("Section %s too small for %d hash table entries\n"),
+ warn (ngettext ("Section %s is too small for %u slot\n",
+ "Section %s is too small for %u slots\n",
+ nslots),
section->name, nslots);
return 0;
}
unsigned int dw_sect;
unsigned char *ph = phash;
unsigned char *pi = pindex;
- unsigned char *poffsets = ppool + ncols * 4;
- unsigned char *psizes = poffsets + nused * ncols * 4;
- unsigned char *pend = psizes + nused * ncols * 4;
+ unsigned char *poffsets = ppool + (size_t) ncols * 4;
+ unsigned char *psizes = poffsets + (size_t) nused * ncols * 4;
+ unsigned char *pend = psizes + (size_t) nused * ncols * 4;
bfd_boolean is_tu_index;
struct cu_tu_set *this_set = NULL;
unsigned int row;
is_tu_index = strcmp (section->name, ".debug_tu_index") == 0;
/* PR 17531: file: 0dd159bf.
- Check for wraparound with an overlarge ncols value. */
- if (poffsets < ppool || (unsigned int) ((poffsets - ppool) / 4) != ncols)
- {
- warn (_("Overlarge number of columns: %x\n"), ncols);
- return 0;
- }
-
- if (pend > limit)
+ Check for integer overflow (can occur when size_t is 32-bit)
+ with overlarge ncols or nused values. */
+ if (ncols > 0
+ && ((size_t) ncols * 4 / 4 != ncols
+ || (size_t) nused * ncols * 4 / ((size_t) ncols * 4) != nused
+ || poffsets < ppool || poffsets > limit
+ || psizes < poffsets || psizes > limit
+ || pend < psizes || pend > limit))
{
warn (_("Section %s too small for offset and size tables\n"),
section->name);