/* dwarf.c -- display DWARF contents of a BFD binary file
- Copyright (C) 2005-2022 Free Software Foundation, Inc.
+ Copyright (C) 2005-2023 Free Software Foundation, Inc.
This file is part of GNU Binutils.
DWO object files. We use these structures to record these links. */
typedef enum dwo_type
{
- DWO_NAME,
- DWO_DIR,
- DWO_ID
+ DWO_NAME,
+ DWO_DIR,
+ DWO_ID
} dwo_type;
typedef struct dwo_info
value & ~(~(uint64_t) 0 << num_bytes * 4 << num_bytes * 4));
}
+static const char *
+null_name (const char *p)
+{
+ if (p == NULL)
+ p = _("unknown");
+ return p;
+}
+
/* Read in a LEB128 encoded value starting at address DATA.
If SIGN is true, return a signed LEB128 value.
If LENGTH_RETURN is not NULL, return in it the number of bytes read.
}
else
SAFE_BYTE_GET (adr, data, len - 1, end);
- printf (_("set Address to 0x%" PRIx64 "\n"), adr);
+ printf (_("set Address to %#" PRIx64 "\n"), adr);
state_machine_regs.address = adr;
state_machine_regs.view = 0;
state_machine_regs.op_index = 0;
return (dwo ? _("<no .debug_str.dwo section>")
: _("<no .debug_str section>"));
- index_offset = idx * offset_size;
-
- if (this_set != NULL)
- index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS];
-
- index_offset += str_offsets_base;
-
- if (index_offset + offset_size > index_section->size)
+ if (_mul_overflow (idx, offset_size, &index_offset)
+ || (this_set != NULL
+ && ((index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS])
+ < this_set->section_offsets [DW_SECT_STR_OFFSETS]))
+ || (index_offset += str_offsets_base) < str_offsets_base
+ || index_offset + offset_size < offset_size
+ || index_offset + offset_size > index_section->size)
{
warn (_("string index of %" PRIu64 " converts to an offset of %#" PRIx64
" which is too big for section %s"),
return _("<string index too big>");
}
- /* FIXME: If we are being paranoid then we should also check to see if
- IDX references an entry beyond the end of the string table pointed to
- by STR_OFFSETS_BASE. (Since there can be more than one string table
- in a DWARF string section). */
-
str_offset = byte_get (index_section->start + index_offset, offset_size);
str_offset -= str_section->address;
return byte_get (section->start + offset, num_bytes);
}
-/* Fetch a value from a debug section that has been indexed by
- something in another section (eg DW_FORM_loclistx or DW_FORM_rnglistx).
- Returns -1 if the value could not be found. */
+/* This is for resolving DW_FORM_rnglistx and DW_FORM_loclistx.
+
+ The memory layout is: base_address (taken from the CU's top DIE) points at a table of offsets,
+ relative to the section start.
+ The table of offsets contains the offsets of objects of interest relative to the table of offsets.
+ IDX is the index of the desired object in said table of offsets.
+
+ This returns the offset of the desired object relative to the section start or -1 upon failure. */
static uint64_t
-fetch_indexed_value (uint64_t idx,
- enum dwarf_section_display_enum sec_enum,
- uint64_t base_address)
+fetch_indexed_offset (uint64_t idx,
+ enum dwarf_section_display_enum sec_enum,
+ uint64_t base_address,
+ uint64_t offset_size)
{
+ uint64_t offset_of_offset = base_address + idx * offset_size;
struct dwarf_section *section = &debug_displays [sec_enum].section;
if (section->start == NULL)
return -1;
}
- uint32_t pointer_size, bias;
-
- if (byte_get (section->start, 4) == 0xffffffff)
- {
- pointer_size = 8;
- bias = 20;
- }
- else
+ if (section->size < 4)
{
- pointer_size = 4;
- bias = 12;
+ warn (_("Section %s is too small to contain an value indexed from another section!\n"),
+ section->name);
+ return -1;
}
- uint64_t offset = idx * pointer_size;
-
- /* Offsets are biased by the size of the section header
- or base address. */
- if (base_address)
- offset += base_address;
- else
- offset += bias;
-
- if (offset + pointer_size > section->size)
+ if (offset_of_offset + offset_size >= section->size)
{
- warn (_("Offset into section %s too big: %#" PRIx64 "\n"),
- section->name, offset);
+ warn (_("Offset of %#" PRIx64 " is too big for section %s\n"),
+ offset_of_offset, section->name);
return -1;
}
-
- return byte_get (section->start + offset, pointer_size);
+
+ return base_address + byte_get (section->start + offset_of_offset, offset_size);
}
/* FIXME: There are better and more efficient ways to handle
list->first_abbrev = NULL;
list->last_abbrev = NULL;
list->raw = start;
+ list->next = NULL;
while (start < end)
{
the caller. */
if (start == end || entry == 0)
{
- list->next = NULL;
list->start_of_next_abbrevs = start != end ? start : NULL;
return list;
}
READ_ULEB (tag, start, end);
if (start == end)
- {
- free (list);
- return NULL;
- }
+ return free_abbrev_list (list);
children = *start++;
/* Report the missing single zero which ends the section. */
error (_("%s section not zero terminated\n"), section->name);
- free (list);
- return NULL;
+ return free_abbrev_list (list);
}
/* Return a sequence of abbrevs in SECTION starting at ABBREV_BASE
/* FIXME: Strictly speaking for 64-bit DWARF3 files
this ought to be an 8-byte wide computation. */
SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
- printf ("DW_OP_call2: <0x%" PRIx64 ">", svalue + cu_offset);
+ printf ("DW_OP_call2: <%#" PRIx64 ">", svalue + cu_offset);
break;
case DW_OP_call4:
/* FIXME: Strictly speaking for 64-bit DWARF3 files
this ought to be an 8-byte wide computation. */
SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end);
- printf ("DW_OP_call4: <0x%" PRIx64 ">", svalue + cu_offset);
+ printf ("DW_OP_call4: <%#" PRIx64 ">", svalue + cu_offset);
break;
case DW_OP_call_ref:
/* FIXME: Strictly speaking for 64-bit DWARF3 files
{
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
}
- printf ("DW_OP_call_ref: <0x%" PRIx64 ">", uvalue);
+ printf ("DW_OP_call_ref: <%#" PRIx64 ">", uvalue);
break;
case DW_OP_form_tls_address:
printf ("DW_OP_form_tls_address");
addr = get_encoded_value (&data, encoding, section, end);
printf ("DW_OP_GNU_encoded_addr: fmt:%02x addr:", encoding);
- print_hex (addr, pointer_size);
+ print_hex_ns (addr, pointer_size);
}
break;
case DW_OP_implicit_pointer:
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
}
READ_SLEB (svalue, data, end);
- printf ("%s: <0x%" PRIx64 "> %" PRId64,
+ printf ("%s: <%#" PRIx64 "> %" PRId64,
(op == DW_OP_implicit_pointer
? "DW_OP_implicit_pointer" : "DW_OP_GNU_implicit_pointer"),
uvalue, svalue);
case DW_OP_const_type:
case DW_OP_GNU_const_type:
READ_ULEB (uvalue, data, end);
- printf ("%s: <0x%" PRIx64 "> ",
+ printf ("%s: <%#" PRIx64 "> ",
(op == DW_OP_const_type ? "DW_OP_const_type"
: "DW_OP_GNU_const_type"),
cu_offset + uvalue);
: "DW_OP_GNU_regval_type"),
uvalue, regname (uvalue, 1));
READ_ULEB (uvalue, data, end);
- printf (" <0x%" PRIx64 ">", cu_offset + uvalue);
+ printf (" <%#" PRIx64 ">", cu_offset + uvalue);
break;
case DW_OP_deref_type:
case DW_OP_GNU_deref_type:
: "DW_OP_GNU_deref_type"),
uvalue);
READ_ULEB (uvalue, data, end);
- printf (" <0x%" PRIx64 ">", cu_offset + uvalue);
+ printf (" <%#" PRIx64 ">", cu_offset + uvalue);
break;
case DW_OP_convert:
case DW_OP_GNU_convert:
READ_ULEB (uvalue, data, end);
- printf ("%s <0x%" PRIx64 ">",
+ printf ("%s <%#" PRIx64 ">",
(op == DW_OP_convert ? "DW_OP_convert" : "DW_OP_GNU_convert"),
uvalue ? cu_offset + uvalue : uvalue);
break;
case DW_OP_reinterpret:
case DW_OP_GNU_reinterpret:
READ_ULEB (uvalue, data, end);
- printf ("%s <0x%" PRIx64 ">",
+ printf ("%s <%#" PRIx64 ">",
(op == DW_OP_reinterpret ? "DW_OP_reinterpret"
: "DW_OP_GNU_reinterpret"),
uvalue ? cu_offset + uvalue : uvalue);
break;
case DW_OP_GNU_parameter_ref:
SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
- printf ("DW_OP_GNU_parameter_ref: <0x%" PRIx64 ">",
+ printf ("DW_OP_GNU_parameter_ref: <%#" PRIx64 ">",
cu_offset + uvalue);
break;
case DW_OP_addrx:
READ_ULEB (uvalue, data, end);
- printf ("DW_OP_addrx <0x%" PRIx64 ">", uvalue);
+ printf ("DW_OP_addrx <%#" PRIx64 ">", uvalue);
break;
case DW_OP_GNU_addr_index:
READ_ULEB (uvalue, data, end);
- printf ("DW_OP_GNU_addr_index <0x%" PRIx64 ">", uvalue);
+ printf ("DW_OP_GNU_addr_index <%#" PRIx64 ">", uvalue);
break;
case DW_OP_GNU_const_index:
READ_ULEB (uvalue, data, end);
- printf ("DW_OP_GNU_const_index <0x%" PRIx64 ">", uvalue);
+ printf ("DW_OP_GNU_const_index <%#" PRIx64 ">", uvalue);
break;
case DW_OP_GNU_variable_value:
/* FIXME: Strictly speaking for 64-bit DWARF3 files
{
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
}
- printf ("DW_OP_GNU_variable_value: <0x%" PRIx64 ">", uvalue);
+ printf ("DW_OP_GNU_variable_value: <%#" PRIx64 ">", uvalue);
break;
/* HP extensions. */
default:
if (op >= DW_OP_lo_user
&& op <= DW_OP_hi_user)
- printf (_("(User defined location op 0x%x)"), op);
+ printf (_("(User defined location op %#x)"), op);
else
- printf (_("(Unknown location op 0x%x)"), op);
+ printf (_("(Unknown location op %#x)"), op);
/* No way to tell where the next op is, so just bail. */
return need_frame_base;
}
printf (")(unsigned)");
}
+static void
+display_lang (uint64_t uvalue)
+{
+ switch (uvalue)
+ {
+ /* Ordered by the numeric value of these constants. */
+ case DW_LANG_C89: printf ("ANSI C"); break;
+ case DW_LANG_C: printf ("non-ANSI C"); break;
+ case DW_LANG_Ada83: printf ("Ada"); break;
+ case DW_LANG_C_plus_plus: printf ("C++"); break;
+ case DW_LANG_Cobol74: printf ("Cobol 74"); break;
+ case DW_LANG_Cobol85: printf ("Cobol 85"); break;
+ case DW_LANG_Fortran77: printf ("FORTRAN 77"); break;
+ case DW_LANG_Fortran90: printf ("Fortran 90"); break;
+ case DW_LANG_Pascal83: printf ("ANSI Pascal"); break;
+ case DW_LANG_Modula2: printf ("Modula 2"); break;
+
+ /* DWARF 2.1 values. */
+ case DW_LANG_Java: printf ("Java"); break;
+ case DW_LANG_C99: printf ("ANSI C99"); break;
+ case DW_LANG_Ada95: printf ("ADA 95"); break;
+ case DW_LANG_Fortran95: printf ("Fortran 95"); break;
+
+ /* DWARF 3 values. */
+ case DW_LANG_PLI: printf ("PLI"); break;
+ case DW_LANG_ObjC: printf ("Objective C"); break;
+ case DW_LANG_ObjC_plus_plus: printf ("Objective C++"); break;
+ case DW_LANG_UPC: printf ("Unified Parallel C"); break;
+ case DW_LANG_D: printf ("D"); break;
+
+ /* DWARF 4 values. */
+ case DW_LANG_Python: printf ("Python"); break;
+
+ /* DWARF 5 values. */
+ case DW_LANG_OpenCL: printf ("OpenCL"); break;
+ case DW_LANG_Go: printf ("Go"); break;
+ case DW_LANG_Modula3: printf ("Modula 3"); break;
+ case DW_LANG_Haskell: printf ("Haskell"); break;
+ case DW_LANG_C_plus_plus_03: printf ("C++03"); break;
+ case DW_LANG_C_plus_plus_11: printf ("C++11"); break;
+ case DW_LANG_OCaml: printf ("OCaml"); break;
+ case DW_LANG_Rust: printf ("Rust"); break;
+ case DW_LANG_C11: printf ("C11"); break;
+ case DW_LANG_Swift: printf ("Swift"); break;
+ case DW_LANG_Julia: printf ("Julia"); break;
+ case DW_LANG_Dylan: printf ("Dylan"); break;
+ case DW_LANG_C_plus_plus_14: printf ("C++14"); break;
+ case DW_LANG_Fortran03: printf ("Fortran 03"); break;
+ case DW_LANG_Fortran08: printf ("Fortran 08"); break;
+ case DW_LANG_RenderScript: printf ("RenderScript"); break;
+
+ /* MIPS extension. */
+ case DW_LANG_Mips_Assembler: printf ("MIPS assembler"); break;
+
+ /* UPC extension. */
+ case DW_LANG_Upc: printf ("Unified Parallel C"); break;
+
+ default:
+ if (uvalue >= DW_LANG_lo_user && uvalue <= DW_LANG_hi_user)
+ printf (_("implementation defined: %#" PRIx64 ""), uvalue);
+ else
+ printf (_("unknown: %#" PRIx64 ""), uvalue);
+ break;
+ }
+}
+
static unsigned char *
read_and_display_attr_value (unsigned long attribute,
unsigned long form,
{
case DW_FORM_ref_addr:
if (!do_loc)
- printf ("%c<0x%" PRIx64 ">", delimiter, uvalue);
+ printf ("%c<%#" PRIx64 ">", delimiter, uvalue);
break;
case DW_FORM_GNU_ref_alt:
{
if (do_wide)
/* We have already printed the form name. */
- printf ("%c<0x%" PRIx64 ">", delimiter, uvalue);
+ printf ("%c<%#" PRIx64 ">", delimiter, uvalue);
else
- printf ("%c<alt 0x%" PRIx64 ">", delimiter, uvalue);
+ printf ("%c<alt %#" PRIx64 ">", delimiter, uvalue);
}
/* FIXME: Follow the reference... */
break;
case DW_FORM_ref_sup4:
case DW_FORM_ref_udata:
if (!do_loc)
- printf ("%c<0x%" PRIx64 ">", delimiter, uvalue + cu_offset);
+ printf ("%c<%#" PRIx64 ">", delimiter, uvalue + cu_offset);
break;
case DW_FORM_data4:
case DW_FORM_addr:
case DW_FORM_sec_offset:
if (!do_loc)
- printf ("%c0x%" PRIx64, delimiter, uvalue);
+ printf ("%c%#" PRIx64, delimiter, uvalue);
break;
case DW_FORM_flag_present:
uint64_t utmp = uvalue;
if (form == DW_FORM_ref8)
utmp += cu_offset;
- printf ("%c0x%" PRIx64, delimiter, utmp);
+ printf ("%c%#" PRIx64, delimiter, utmp);
}
break;
if (!do_loc)
{
if (uvalue_hi == 0)
- printf (" 0x%" PRIx64, uvalue);
+ printf (" %#" PRIx64, uvalue);
else
- printf (" 0x%" PRIx64 "%016" PRIx64, uvalue_hi, uvalue);
+ printf (" %#" PRIx64 "%016" PRIx64, uvalue_hi, uvalue);
}
break;
{
if (do_wide)
/* We have already displayed the form name. */
- printf (_("%c(offset: 0x%" PRIx64 "): %s"),
+ printf (_("%c(offset: %#" PRIx64 "): %s"),
delimiter, uvalue, fetch_indirect_string (uvalue));
else
- printf (_("%c(indirect string, offset: 0x%" PRIx64 "): %s"),
+ printf (_("%c(indirect string, offset: %#" PRIx64 "): %s"),
delimiter, uvalue, fetch_indirect_string (uvalue));
}
break;
{
if (do_wide)
/* We have already displayed the form name. */
- printf (_("%c(offset: 0x%" PRIx64 "): %s"),
+ printf (_("%c(offset: %#" PRIx64 "): %s"),
delimiter, uvalue, fetch_indirect_line_string (uvalue));
else
- printf (_("%c(indirect line string, offset: 0x%" PRIx64 "): %s"),
+ printf (_("%c(indirect line string, offset: %#" PRIx64 "): %s"),
delimiter, uvalue, fetch_indirect_line_string (uvalue));
}
break;
debug_info_p ? debug_info_p->str_offsets_base : 0);
if (do_wide)
/* We have already displayed the form name. */
- printf (_("%c(offset: 0x%" PRIx64 "): %s"),
+ printf (_("%c(offset: %#" PRIx64 "): %s"),
delimiter, uvalue, strng);
else
- printf (_("%c(indexed string: 0x%" PRIx64 "): %s"),
+ printf (_("%c(indexed string: %#" PRIx64 "): %s"),
delimiter, uvalue, strng);
}
break;
{
if (do_wide)
/* We have already displayed the form name. */
- printf (_("%c(offset: 0x%" PRIx64 ") %s"),
+ printf (_("%c(offset: %#" PRIx64 ") %s"),
delimiter, uvalue, fetch_alt_indirect_string (uvalue));
else
- printf (_("%c(alt indirect string, offset: 0x%" PRIx64 ") %s"),
+ printf (_("%c(alt indirect string, offset: %#" PRIx64 ") %s"),
delimiter, uvalue, fetch_alt_indirect_string (uvalue));
}
break;
case DW_FORM_ref_sig8:
if (!do_loc)
- printf ("%c%s: 0x%" PRIx64, delimiter, do_wide ? "" : "signature",
+ printf ("%c%s: %#" PRIx64, delimiter, do_wide ? "" : "signature",
uvalue);
break;
{
if (dwo)
{
- idx = fetch_indexed_value (uvalue, loclists_dwo, 0);
+ idx = fetch_indexed_offset (uvalue, loclists_dwo,
+ debug_info_p->loclists_base,
+ debug_info_p->offset_size);
if (idx != (uint64_t) -1)
idx += (offset_size == 8) ? 20 : 12;
}
- else if (debug_info_p == NULL)
+ else if (debug_info_p == NULL || dwarf_version > 4)
{
- idx = fetch_indexed_value (uvalue, loclists, 0);
+ idx = fetch_indexed_offset (uvalue, loclists,
+ debug_info_p->loclists_base,
+ debug_info_p->offset_size);
}
else
{
/* We want to compute:
- idx = fetch_indexed_value (uvalue, loclists, debug_info_p->loclists_base);
+ idx = fetch_indexed_value (uvalue, loclists,
+ debug_info_p->loclists_base);
idx += debug_info_p->loclists_base;
Fortunately we already have that sum cached in the
loc_offsets array. */
{
if (dwo)
{
- idx = fetch_indexed_value (uvalue, rnglists_dwo, 0);
- if (idx != (uint64_t) -1)
- idx += (offset_size == 8) ? 20 : 12;
+ idx = fetch_indexed_offset (uvalue, rnglists,
+ debug_info_p->rnglists_base,
+ debug_info_p->offset_size);
}
else
{
base = 0;
else
base = debug_info_p->rnglists_base;
- /* We do not have a cached value this time, so we perform the
- computation manually. */
- idx = fetch_indexed_value (uvalue, rnglists, base);
- if (idx != (uint64_t) -1)
- idx += base;
+ idx = fetch_indexed_offset (uvalue, rnglists, base,
+ debug_info_p->offset_size);
}
}
else
/* We have already displayed the form name. */
if (idx != (uint64_t) -1)
- printf (_("%c(index: 0x%" PRIx64 "): %" PRIx64),
+ printf (_("%c(index: %#" PRIx64 "): %#" PRIx64),
delimiter, uvalue, idx);
}
break;
case DW_FORM_strp_sup:
if (!do_loc)
- printf ("%c<0x%" PRIx64 ">", delimiter, uvalue + cu_offset);
+ printf ("%c<%#" PRIx64 ">", delimiter, uvalue + cu_offset);
break;
default:
- warn (_("Unrecognized form: 0x%lx\n"), form);
+ warn (_("Unrecognized form: %#lx"), form);
/* What to do? Consume a byte maybe? */
++data;
break;
"(%#" PRIx64 " and %#" PRIx64 ")"),
debug_info_p->cu_offset,
debug_info_p->loclists_base, uvalue);
+ svalue = uvalue;
+ if (svalue < 0)
+ {
+ warn (_("CU @ %#" PRIx64 " has has a negative loclists_base "
+ "value of %#" PRIx64 " - treating as zero"),
+ debug_info_p->cu_offset, svalue);
+ uvalue = 0;
+ }
debug_info_p->loclists_base = uvalue;
break;
- case DW_AT_rnglists_base:
- if (debug_info_p->rnglists_base)
- warn (_("CU @ %#" PRIx64 " has multiple rnglists_base values "
- "(%#" PRIx64 " and %#" PRIx64 ")"),
- debug_info_p->cu_offset,
- debug_info_p->rnglists_base, uvalue);
- debug_info_p->rnglists_base = uvalue;
- break;
+
+ case DW_AT_rnglists_base:
+ /* Assignment to debug_info_p->rnglists_base is now elsewhere. */
+ break;
+
case DW_AT_str_offsets_base:
if (debug_info_p->str_offsets_base)
warn (_("CU @ %#" PRIx64 " has multiple str_offsets_base values "
"%#" PRIx64 " and %#" PRIx64 ")"),
debug_info_p->cu_offset,
debug_info_p->str_offsets_base, uvalue);
+ svalue = uvalue;
+ if (svalue < 0)
+ {
+ warn (_("CU @ %#" PRIx64 " has has a negative stroffsets_base "
+ "value of %#" PRIx64 " - treating as zero"),
+ debug_info_p->cu_offset, svalue);
+ uvalue = 0;
+ }
debug_info_p->str_offsets_base = uvalue;
break;
debug_info_p->max_loc_offsets = lmax;
}
if (form == DW_FORM_loclistx)
- uvalue = fetch_indexed_value (num, loclists, debug_info_p->loclists_base);
+ uvalue = fetch_indexed_offset (num, loclists,
+ debug_info_p->loclists_base,
+ debug_info_p->offset_size);
else if (this_set != NULL)
uvalue += this_set->section_offsets [DW_SECT_LOC];
}
else
{
- assert (debug_info_p->num_loc_views <= num);
- num = debug_info_p->num_loc_views;
+ if (debug_info_p->num_loc_views > num)
+ {
+ warn (_("The number of views (%u) is greater than the number of locations (%u)\n"),
+ debug_info_p->num_loc_views, num);
+ debug_info_p->num_loc_views = num;
+ }
+ else
+ num = debug_info_p->num_loc_views;
if (num > debug_info_p->num_loc_offsets)
warn (_("More DW_AT_GNU_locview attributes than location offset attributes\n"));
else
case DW_AT_low_pc:
if (need_base_address)
- debug_info_p->base_address = uvalue;
+ {
+ if (form == DW_FORM_addrx)
+ uvalue = fetch_indexed_addr (debug_info_p->addr_base
+ + uvalue * pointer_size,
+ pointer_size);
+
+ debug_info_p->base_address = uvalue;
+ }
break;
case DW_AT_GNU_addr_base:
case DW_AT_addr_base:
debug_info_p->addr_base = uvalue;
+ /* Retrieved elsewhere so that it is in
+ place by the time we read low_pc. */
break;
case DW_AT_GNU_ranges_base:
}
if (form == DW_FORM_rnglistx)
- uvalue = fetch_indexed_value (uvalue, rnglists, 0);
+ uvalue = fetch_indexed_offset (uvalue, rnglists,
+ debug_info_p->rnglists_base,
+ debug_info_p->offset_size);
debug_info_p->range_lists [num] = uvalue;
debug_info_p->num_range_lists++;
switch (form)
{
case DW_FORM_strp:
- add_dwo_name ((const char *) fetch_indirect_string (uvalue), cu_offset);
+ add_dwo_name ((const char *) fetch_indirect_string (uvalue),
+ cu_offset);
break;
case DW_FORM_GNU_strp_alt:
add_dwo_name ((const char *) fetch_alt_indirect_string (uvalue), cu_offset);
case DW_FORM_strx2:
case DW_FORM_strx3:
case DW_FORM_strx4:
- add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, false,
+ add_dwo_name (fetch_indexed_string (uvalue, this_set,
+ offset_size, false,
debug_info_p->str_offsets_base),
cu_offset);
break;
break;
case DW_AT_language:
- printf ("\t");
- switch (uvalue)
- {
- /* Ordered by the numeric value of these constants. */
- case DW_LANG_C89: printf ("(ANSI C)"); break;
- case DW_LANG_C: printf ("(non-ANSI C)"); break;
- case DW_LANG_Ada83: printf ("(Ada)"); break;
- case DW_LANG_C_plus_plus: printf ("(C++)"); break;
- case DW_LANG_Cobol74: printf ("(Cobol 74)"); break;
- case DW_LANG_Cobol85: printf ("(Cobol 85)"); break;
- case DW_LANG_Fortran77: printf ("(FORTRAN 77)"); break;
- case DW_LANG_Fortran90: printf ("(Fortran 90)"); break;
- case DW_LANG_Pascal83: printf ("(ANSI Pascal)"); break;
- case DW_LANG_Modula2: printf ("(Modula 2)"); break;
- /* DWARF 2.1 values. */
- case DW_LANG_Java: printf ("(Java)"); break;
- case DW_LANG_C99: printf ("(ANSI C99)"); break;
- case DW_LANG_Ada95: printf ("(ADA 95)"); break;
- case DW_LANG_Fortran95: printf ("(Fortran 95)"); break;
- /* DWARF 3 values. */
- case DW_LANG_PLI: printf ("(PLI)"); break;
- case DW_LANG_ObjC: printf ("(Objective C)"); break;
- case DW_LANG_ObjC_plus_plus: printf ("(Objective C++)"); break;
- case DW_LANG_UPC: printf ("(Unified Parallel C)"); break;
- case DW_LANG_D: printf ("(D)"); break;
- /* DWARF 4 values. */
- case DW_LANG_Python: printf ("(Python)"); break;
- /* DWARF 5 values. */
- case DW_LANG_OpenCL: printf ("(OpenCL)"); break;
- case DW_LANG_Go: printf ("(Go)"); break;
- case DW_LANG_Modula3: printf ("(Modula 3)"); break;
- case DW_LANG_Haskell: printf ("(Haskell)"); break;
- case DW_LANG_C_plus_plus_03: printf ("(C++03)"); break;
- case DW_LANG_C_plus_plus_11: printf ("(C++11)"); break;
- case DW_LANG_OCaml: printf ("(OCaml)"); break;
- case DW_LANG_Rust: printf ("(Rust)"); break;
- case DW_LANG_C11: printf ("(C11)"); break;
- case DW_LANG_Swift: printf ("(Swift)"); break;
- case DW_LANG_Julia: printf ("(Julia)"); break;
- case DW_LANG_Dylan: printf ("(Dylan)"); break;
- case DW_LANG_C_plus_plus_14: printf ("(C++14)"); break;
- case DW_LANG_Fortran03: printf ("(Fortran 03)"); break;
- case DW_LANG_Fortran08: printf ("(Fortran 08)"); break;
- case DW_LANG_RenderScript: printf ("(RenderScript)"); break;
- /* MIPS extension. */
- case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
- /* UPC extension. */
- case DW_LANG_Upc: printf ("(Unified Parallel C)"); break;
- default:
- if (uvalue >= DW_LANG_lo_user && uvalue <= DW_LANG_hi_user)
- printf (_("(implementation defined: %#" PRIx64 ")"), uvalue);
- else
- printf (_("(unknown: %#" PRIx64 ")"), uvalue);
- break;
- }
+ printf ("\t(");
+ display_lang (uvalue);
+ printf (")");
break;
case DW_AT_encoding:
}
}
+/* Free memory allocated for one unit in debug_information. */
+
+static void
+free_debug_information (debug_info *ent)
+{
+ if (ent->max_loc_offsets)
+ {
+ free (ent->loc_offsets);
+ free (ent->loc_views);
+ free (ent->have_frame_base);
+ }
+ if (ent->max_range_lists)
+ {
+ free (ent->range_lists);
+ }
+}
+
+/* For look-ahead in attributes. When you want to scan a DIE for one specific
+ attribute and ignore the rest. */
+
+static unsigned char *
+skip_attribute (unsigned long form,
+ unsigned char * data,
+ unsigned char * end,
+ uint64_t pointer_size,
+ uint64_t offset_size,
+ int dwarf_version)
+{
+ uint64_t temp;
+ int64_t stemp;
+
+ switch (form)
+ {
+ case DW_FORM_ref_addr:
+ data += dwarf_version == 2 ? pointer_size : offset_size;
+ break;
+ case DW_FORM_addr:
+ data += pointer_size;
+ break;
+ case DW_FORM_strp_sup:
+ 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:
+ data += offset_size;
+ break;
+ case DW_FORM_ref1:
+ case DW_FORM_flag:
+ case DW_FORM_data1:
+ case DW_FORM_strx1:
+ case DW_FORM_addrx1:
+ data += 1;
+ break;
+ case DW_FORM_ref2:
+ case DW_FORM_data2:
+ case DW_FORM_strx2:
+ case DW_FORM_addrx2:
+ data += 2;
+ break;
+ case DW_FORM_strx3:
+ case DW_FORM_addrx3:
+ data += 3;
+ break;
+ case DW_FORM_ref_sup4:
+ case DW_FORM_ref4:
+ case DW_FORM_data4:
+ case DW_FORM_strx4:
+ case DW_FORM_addrx4:
+ data += 4;
+ break;
+ case DW_FORM_ref_sup8:
+ case DW_FORM_ref8:
+ case DW_FORM_data8:
+ case DW_FORM_ref_sig8:
+ data += 8;
+ break;
+ case DW_FORM_data16:
+ data += 16;
+ break;
+ case DW_FORM_sdata:
+ READ_SLEB (stemp, data, end);
+ break;
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_strx:
+ case DW_FORM_ref_udata:
+ case DW_FORM_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_addrx:
+ case DW_FORM_loclistx:
+ case DW_FORM_rnglistx:
+ READ_ULEB (temp, data, end);
+ break;
+
+ case DW_FORM_indirect:
+ while (form == DW_FORM_indirect)
+ READ_ULEB (form, data, end);
+ return skip_attribute (form, data, end, pointer_size, offset_size, dwarf_version);
+
+ case DW_FORM_string:
+ data += strnlen ((char *) data, end - data);
+ break;
+ case DW_FORM_block:
+ case DW_FORM_exprloc:
+ READ_ULEB (temp, data, end);
+ data += temp;
+ break;
+ case DW_FORM_block1:
+ SAFE_BYTE_GET_AND_INC (temp, data, 1, end);
+ data += temp;
+ break;
+ case DW_FORM_block2:
+ SAFE_BYTE_GET_AND_INC (temp, data, 2, end);
+ data += temp;
+ break;
+ case DW_FORM_block4:
+ SAFE_BYTE_GET_AND_INC (temp, data, 4, end);
+ data += temp;
+ break;
+ case DW_FORM_implicit_const:
+ case DW_FORM_flag_present:
+ break;
+ default:
+ warn (_("Unexpected form in top DIE\n"));
+ break;
+ }
+ return data;
+}
+
+static void
+read_bases (abbrev_entry * entry,
+ unsigned char * data,
+ unsigned char * end,
+ int64_t pointer_size,
+ uint64_t offset_size,
+ int dwarf_version,
+ debug_info * debug_info_p)
+{
+ abbrev_attr *attr;
+
+ for (attr = entry->first_attr;
+ attr && attr->attribute;
+ attr = attr->next)
+ {
+ uint64_t uvalue;
+
+ if (attr->attribute == DW_AT_rnglists_base)
+ {
+ if (attr->form == DW_FORM_sec_offset)
+ {
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ debug_info_p->rnglists_base = uvalue;
+ }
+ else
+ warn (_("Unexpected form of DW_AT_rnglists_base in the top DIE\n"));
+ }
+ else if(attr->attribute == DW_AT_addr_base || attr->attribute == DW_AT_GNU_addr_base)
+ {
+ if (attr->form == DW_FORM_sec_offset)
+ {
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ debug_info_p->addr_base = uvalue;
+ }
+ else
+ warn (_("Unexpected form of DW_AT_addr_base in the top DIE\n"));
+ }
+ else
+ data = skip_attribute(attr->form, data, end, pointer_size, offset_size, dwarf_version);
+ }
+}
+
/* Process the contents of a .debug_info section.
If do_loc is TRUE then we are scanning for location lists and dwo tags
and we do not want to display anything to the user.
&& alloc_num_debug_info_entries > unit
&& ! do_types)
{
- debug_information [unit].cu_offset = cu_offset;
- debug_information [unit].pointer_size
- = compunit.cu_pointer_size;
- debug_information [unit].offset_size = offset_size;
- debug_information [unit].dwarf_version = compunit.cu_version;
- debug_information [unit].base_address = 0;
- debug_information [unit].addr_base = DEBUG_INFO_UNAVAILABLE;
- debug_information [unit].ranges_base = DEBUG_INFO_UNAVAILABLE;
- debug_information [unit].rnglists_base = 0;
- debug_information [unit].loc_offsets = NULL;
- debug_information [unit].have_frame_base = NULL;
- debug_information [unit].max_loc_offsets = 0;
- debug_information [unit].num_loc_offsets = 0;
- debug_information [unit].loclists_base = 0;
- debug_information [unit].range_lists = NULL;
- debug_information [unit].max_range_lists= 0;
- debug_information [unit].num_range_lists = 0;
- debug_information [unit].rnglists_base = 0;
- debug_information [unit].str_offsets_base = 0;
+ free_debug_information (&debug_information[unit]);
+ memset (&debug_information[unit], 0, sizeof (*debug_information));
+ debug_information[unit].pointer_size = compunit.cu_pointer_size;
+ debug_information[unit].offset_size = offset_size;
+ debug_information[unit].dwarf_version = compunit.cu_version;
+ debug_information[unit].cu_offset = cu_offset;
+ debug_information[unit].addr_base = DEBUG_INFO_UNAVAILABLE;
+ debug_information[unit].ranges_base = DEBUG_INFO_UNAVAILABLE;
}
if (!do_loc && dwarf_start_die == 0)
{
- printf (_(" Compilation Unit @ offset 0x%" PRIx64 ":\n"),
+ printf (_(" Compilation Unit @ offset %#" PRIx64 ":\n"),
cu_offset);
- printf (_(" Length: 0x%" PRIx64 " (%s)\n"),
+ printf (_(" Length: %#" PRIx64 " (%s)\n"),
compunit.cu_length,
offset_size == 8 ? "64-bit" : "32-bit");
printf (_(" Version: %d\n"), compunit.cu_version);
const char *name = get_DW_UT_name (compunit.cu_unit_type);
printf (_(" Unit Type: %s (%x)\n"),
- name ? name : "???",
+ null_name (name),
compunit.cu_unit_type);
}
- printf (_(" Abbrev Offset: 0x%" PRIx64 "\n"),
+ printf (_(" Abbrev Offset: %#" PRIx64 "\n"),
compunit.cu_abbrev_offset);
printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size);
if (do_types)
{
- printf (_(" Signature: 0x%" PRIx64 "\n"), signature);
- printf (_(" Type Offset: 0x%" PRIx64 "\n"), type_offset);
+ printf (_(" Signature: %#" PRIx64 "\n"), signature);
+ printf (_(" Type Offset: %#" PRIx64 "\n"), type_offset);
}
if (do_dwo_id)
- printf (_(" DWO ID: 0x%" PRIx64 "\n"), dwo_id);
+ printf (_(" DWO ID: %#" PRIx64 "\n"), dwo_id);
if (this_set != NULL)
{
uint64_t *offsets = this_set->section_offsets;
size_t *sizes = this_set->section_sizes;
printf (_(" Section contributions:\n"));
- printf (_(" .debug_abbrev.dwo: 0x%" PRIx64 " 0x%zx\n"),
+ printf (_(" .debug_abbrev.dwo: %#" PRIx64 " %#zx\n"),
offsets[DW_SECT_ABBREV], sizes[DW_SECT_ABBREV]);
- printf (_(" .debug_line.dwo: 0x%" PRIx64 " 0x%zx\n"),
+ printf (_(" .debug_line.dwo: %#" PRIx64 " %#zx\n"),
offsets[DW_SECT_LINE], sizes[DW_SECT_LINE]);
- printf (_(" .debug_loc.dwo: 0x%" PRIx64 " 0x%zx\n"),
+ printf (_(" .debug_loc.dwo: %#" PRIx64 " %#zx\n"),
offsets[DW_SECT_LOC], sizes[DW_SECT_LOC]);
- printf (_(" .debug_str_offsets.dwo: 0x%" PRIx64 " 0x%zx\n"),
+ printf (_(" .debug_str_offsets.dwo: %#" PRIx64 " %#zx\n"),
offsets[DW_SECT_STR_OFFSETS], sizes[DW_SECT_STR_OFFSETS]);
}
}
}
}
if (dwarf_start_die != 0 && level < saved_level)
- return true;
+ {
+ if (list != NULL)
+ free_abbrev_list (list);
+ return true;
+ }
continue;
}
}
warn (_("DIE at offset %#lx refers to abbreviation number %lu which does not exist\n"),
die_offset, abbrev_number);
+ if (list != NULL)
+ free_abbrev_list (list);
return false;
}
|| (debug_info_p->num_loc_offsets
== debug_info_p->num_loc_views));
+ /* Look ahead so that the values of DW_AT_rnglists_base, DW_AT_[GNU_]addr_base
+ are available before attributes that reference them are parsed in the same DIE.
+ Only needed for the top DIE on DWARFv5+.
+ No simiar treatment for loclists_base because there should be no loclist
+ attributes in top DIE. */
+ if (compunit.cu_version >= 5 && level == 0)
+ {
+ int64_t stemp;
+
+ read_bases (entry,
+ tags,
+ start,
+ compunit.cu_pointer_size,
+ offset_size,
+ compunit.cu_version,
+ debug_info_p);
+
+ /* This check was in place before, keep it. */
+ stemp = debug_info_p->rnglists_base;
+ if (stemp < 0)
+ {
+ warn (_("CU @ %#" PRIx64 " has has a negative rnglists_base "
+ "value of %#" PRIx64 " - treating as zero"),
+ debug_info_p->cu_offset, stemp);
+ debug_info_p->rnglists_base = 0;
+ }
+ }
+
for (attr = entry->first_attr;
attr && attr->attribute;
attr = attr->next)
printf (_("\n The %s is empty.\n"), table_name);
return data;
}
- else if (data >= end)
+ else if (data >= end
+ || data_count > (size_t) (end - data))
{
- warn (_("%s: Corrupt entry count - expected %#" PRIx64
- " but none found\n"), table_name, data_count);
+ warn (_("%s: Corrupt entry count %#" PRIx64 "\n"), table_name, data_count);
return data;
}
return end;
}
- printf (_("\n The %s (offset 0x%tx, lines %" PRIu64 ", columns %u):\n"),
+ printf (_("\n The %s (offset %#tx, lines %" PRIu64 ", columns %u):\n"),
table_name, data - start, data_count, format_count);
printf (_(" Entry"));
& end_of_sequence)) == NULL)
return 0;
- printf (_(" Offset: 0x%tx\n"), data - start);
+ printf (_(" Offset: %#tx\n"), data - start);
printf (_(" Length: %" PRId64 "\n"), linfo.li_length);
printf (_(" DWARF Version: %d\n"), linfo.li_version);
if (linfo.li_version >= 5)
{
unsigned int last_dir_entry = 0;
- printf (_("\n The Directory Table (offset 0x%tx):\n"),
+ printf (_("\n The Directory Table (offset %#tx):\n"),
data - start);
while (data < end && *data != 0)
printf (_("\n The File Name Table is empty.\n"));
else
{
- printf (_("\n The File Name Table (offset 0x%tx):\n"),
+ printf (_("\n The File Name Table (offset %#tx):\n"),
data - start);
printf (_(" Entry\tDir\tTime\tSize\tName\n"));
while (data < end_of_sequence)
{
unsigned char op_code;
- int64_t adv;
+ int adv;
uint64_t uladv;
printf (" [0x%08tx]", data - start);
state_machine_regs.view = 0;
printf (_(" Special opcode %d: "
"advance Address by %" PRIu64
- " to 0x%" PRIx64 "%s"),
+ " to %#" PRIx64 "%s"),
op_code, uladv, state_machine_regs.address,
verbose_view && uladv
? _(" (reset view)") : "");
state_machine_regs.view = 0;
printf (_(" Special opcode %d: "
"advance Address by %" PRIu64
- " to 0x%" PRIx64 "[%d]%s"),
+ " to %#" PRIx64 "[%d]%s"),
op_code, uladv, state_machine_regs.address,
state_machine_regs.op_index,
verbose_view && addrdelta
}
adv = (op_code % linfo.li_line_range) + linfo.li_line_base;
state_machine_regs.line += adv;
- printf (_(" and Line by %" PRId64 " to %d"),
+ printf (_(" and Line by %d to %d"),
adv, state_machine_regs.line);
if (verbose_view || state_machine_regs.view)
printf (_(" (view %u)\n"), state_machine_regs.view);
if (uladv)
state_machine_regs.view = 0;
printf (_(" Advance PC by %" PRIu64
- " to 0x%" PRIx64 "%s\n"),
+ " to %#" PRIx64 "%s\n"),
uladv, state_machine_regs.address,
verbose_view && uladv
? _(" (reset view)") : "");
if (addrdelta)
state_machine_regs.view = 0;
printf (_(" Advance PC by %" PRIu64
- " to 0x%" PRIx64 "[%d]%s\n"),
+ " to %#" PRIx64 "[%d]%s\n"),
uladv, state_machine_regs.address,
state_machine_regs.op_index,
verbose_view && addrdelta
case DW_LNS_advance_line:
READ_SLEB (adv, data, end);
state_machine_regs.line += adv;
- printf (_(" Advance Line by %" PRId64 " to %d\n"),
+ printf (_(" Advance Line by %d to %d\n"),
adv, state_machine_regs.line);
break;
case DW_LNS_negate_stmt:
adv = state_machine_regs.is_stmt;
adv = ! adv;
- printf (_(" Set is_stmt to %" PRId64 "\n"), adv);
+ printf (_(" Set is_stmt to %d\n"), adv);
state_machine_regs.is_stmt = adv;
break;
if (uladv)
state_machine_regs.view = 0;
printf (_(" Advance PC by constant %" PRIu64
- " to 0x%" PRIx64 "%s\n"),
+ " to %#" PRIx64 "%s\n"),
uladv, state_machine_regs.address,
verbose_view && uladv
? _(" (reset view)") : "");
if (addrdelta)
state_machine_regs.view = 0;
printf (_(" Advance PC by constant %" PRIu64
- " to 0x%" PRIx64 "[%d]%s\n"),
+ " to %#" PRIx64 "[%d]%s\n"),
uladv, state_machine_regs.address,
state_machine_regs.op_index,
verbose_view && addrdelta
state_machine_regs.address += uladv;
state_machine_regs.op_index = 0;
printf (_(" Advance PC by fixed size amount %" PRIu64
- " to 0x%" PRIx64 "\n"),
+ " to %#" PRIx64 "\n"),
uladv, state_machine_regs.address);
/* Do NOT reset view. */
break;
for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
{
READ_ULEB (uladv, data, end);
- printf ("0x%" PRIx64 "%s", uladv, i == 1 ? "" : ", ");
+ printf ("%#" PRIx64 "%s", uladv, i == 1 ? "" : ", ");
}
putchar ('\n');
break;
typedef struct
{
- unsigned char *name;
+ char *name;
unsigned int directory_index;
unsigned int modification_date;
unsigned int length;
int i;
File_Entry *file_table = NULL;
unsigned int n_files = 0;
- unsigned char **directory_table = NULL;
- uint64_t n_directories = 0;
+ char **directory_table = NULL;
+ unsigned int n_directories = 0;
if (startswith (section->name, ".debug_line.")
/* Note: the following does not apply to .debug_line.dwo sections.
if (linfo.li_version >= 5)
{
- unsigned char *format_start, format_count, *format;
- uint64_t formati, entryi;
+ unsigned char *format_start, *format;
+ unsigned int format_count, formati, entryi;
load_debug_section_with_follow (line_str, fileptr);
if (n_directories == 0)
directory_table = NULL;
+ else if (n_directories > section->size)
+ {
+ warn (_("number of directories (0x%x) exceeds size of section %s\n"),
+ n_directories, section->name);
+ return 0;
+ }
else
- directory_table = (unsigned char **)
- xmalloc (n_directories * sizeof (unsigned char *));
+ directory_table = (char **)
+ xcalloc (n_directories, sizeof (unsigned char *));
for (entryi = 0; entryi < n_directories; entryi++)
{
- unsigned char **pathp = &directory_table[entryi];
+ char **pathp = &directory_table[entryi];
format = format_start;
for (formati = 0; formati < format_count; formati++)
switch (form)
{
case DW_FORM_string:
- *pathp = data;
+ *pathp = (char *) data;
break;
case DW_FORM_line_strp:
SAFE_BYTE_GET (uvalue, data, linfo.li_offset_size,
end);
/* Remove const by the cast. */
- *pathp = (unsigned char *)
+ *pathp = (char *)
fetch_indirect_line_string (uvalue);
break;
}
if (do_checks && format_count > 5)
warn (_("Unexpectedly large number of columns in the file name table (%u)\n"),
format_count);
+
format_start = data;
for (formati = 0; formati < format_count; formati++)
{
if (n_files == 0)
file_table = NULL;
+ else if (n_files > section->size)
+ {
+ warn (_("number of files (0x%x) exceeds size of section %s\n"),
+ n_files, section->name);
+ return 0;
+ }
else
- file_table = (File_Entry *) xcalloc (1, n_files
- * sizeof (File_Entry));
+ file_table = (File_Entry *) xcalloc (n_files,
+ sizeof (File_Entry));
for (entryi = 0; entryi < n_files; entryi++)
{
switch (form)
{
case DW_FORM_string:
- file->name = data;
+ file->name = (char *) data;
break;
case DW_FORM_line_strp:
SAFE_BYTE_GET (uvalue, data, linfo.li_offset_size,
end);
/* Remove const by the cast. */
- file->name = (unsigned char *)
+ file->name = (char *)
fetch_indirect_line_string (uvalue);
break;
}
{
if (*data != 0)
{
- unsigned char *ptr_directory_table = data;
+ char *ptr_directory_table = (char *) data;
while (data < end && *data != 0)
{
}
/* Go through the directory table again to save the directories. */
- directory_table = (unsigned char **)
+ directory_table = (char **)
xmalloc (n_directories * sizeof (unsigned char *));
i = 0;
while (*ptr_directory_table != 0)
{
directory_table[i] = ptr_directory_table;
- ptr_directory_table
- += strlen ((char *) ptr_directory_table) + 1;
+ ptr_directory_table += strlen (ptr_directory_table) + 1;
i++;
}
}
i = 0;
while (*ptr_file_name_table != 0)
{
- file_table[i].name = ptr_file_name_table;
+ file_table[i].name = (char *) ptr_file_name_table;
ptr_file_name_table
+= strlen ((char *) ptr_file_name_table) + 1;
if (file_table == NULL)
printf (_("CU: No directory table\n"));
else if (directory_table == NULL)
- printf (_("CU: %s:\n"), file_table[0].name);
+ printf (_("CU: %s:\n"), null_name (file_table[0].name));
else
{
unsigned int ix = file_table[0].directory_index;
const char *directory;
- if (ix == 0)
+ if (ix == 0 && linfo.li_version < 5)
directory = ".";
/* PR 20439 */
else if (n_directories == 0)
directory = _("<unknown>");
- else if (ix > n_directories)
+ else
{
- warn (_("directory index %u > number of directories %" PRIu64 "\n"),
- ix, n_directories);
- directory = _("<corrupt>");
+ if (linfo.li_version < 5)
+ --ix;
+ if (ix >= n_directories)
+ {
+ warn (_("directory index %u "
+ ">= number of directories %u\n"),
+ ix, n_directories);
+ directory = _("<corrupt>");
+ }
+ else
+ directory = directory_table[ix];
}
- else
- directory = (char *) directory_table[ix - 1];
-
if (do_wide)
- printf (_("CU: %s/%s:\n"), directory, file_table[0].name);
+ printf (_("CU: %s/%s:\n"),
+ null_name (directory),
+ null_name (file_table[0].name));
else
- printf ("%s:\n", file_table[0].name);
+ printf ("%s:\n", null_name (file_table[0].name));
}
if (n_files > 0)
- printf (_("File name Line number Starting address View Stmt\n"));
+ {
+ if (do_wide)
+ printf (_("File name Line number Starting address View Stmt\n"));
+ else
+ printf (_("File name Line number Starting address View Stmt\n"));
+ }
else
printf (_("CU: Empty file name table\n"));
saved_linfo = linfo;
++state_machine_regs.last_file_entry;
/* Source file name. */
- file_table[n_files].name = op_code_data;
+ file_table[n_files].name = (char *) op_code_data;
op_code_data += strlen ((char *) op_code_data) + 1;
/* Directory index. */
READ_ULEB (file_table[n_files].directory_index,
READ_ULEB (uladv, data, end);
state_machine_regs.file = uladv;
- {
- unsigned file = state_machine_regs.file;
- unsigned dir;
+ unsigned file = state_machine_regs.file;
+ if (linfo.li_version < 5)
+ --file;
- if (linfo.li_version < 5)
- --file;
- if (file_table == NULL || n_files == 0)
- printf (_("\n [Use file table entry %d]\n"), file);
- /* PR 20439 */
- else if (file >= n_files)
- {
- warn (_("file index %u > number of files %u\n"), file, n_files);
- printf (_("\n <over large file table index %u>"), file);
- }
- else if ((dir = file_table[file].directory_index) == 0)
- /* If directory index is 0, that means current directory. */
- printf ("\n./%s:[++]\n", file_table[file].name);
- else if (directory_table == NULL || n_directories == 0)
- printf (_("\n [Use file %s in directory table entry %d]\n"),
- file_table[file].name, dir);
- /* PR 20439 */
- else if (dir > n_directories)
- {
- warn (_("directory index %u > number of directories %" PRIu64 "\n"),
- dir, n_directories);
- printf (_("\n <over large directory table entry %u>\n"), dir);
- }
- else
- printf ("\n%s/%s:\n",
- /* The directory index starts counting at 1. */
- directory_table[dir - 1], file_table[file].name);
- }
+ if (file_table == NULL || n_files == 0)
+ printf (_("\n [Use file table entry %d]\n"), file);
+ /* PR 20439 */
+ else if (file >= n_files)
+ {
+ warn (_("file index %u >= number of files %u\n"),
+ file, n_files);
+ printf (_("\n <over large file table index %u>"), file);
+ }
+ else
+ {
+ unsigned dir = file_table[file].directory_index;
+ if (dir == 0 && linfo.li_version < 5)
+ /* If directory index is 0, that means compilation
+ current directory. bfd/dwarf2.c shows
+ DW_AT_comp_dir here but in keeping with the
+ readelf practice of minimal interpretation of
+ file data, we show "./". */
+ printf ("\n./%s:[++]\n",
+ null_name (file_table[file].name));
+ else if (directory_table == NULL || n_directories == 0)
+ printf (_("\n [Use file %s "
+ "in directory table entry %d]\n"),
+ null_name (file_table[file].name), dir);
+ else
+ {
+ if (linfo.li_version < 5)
+ --dir;
+ /* PR 20439 */
+ if (dir >= n_directories)
+ {
+ warn (_("directory index %u "
+ ">= number of directories %u\n"),
+ dir, n_directories);
+ printf (_("\n <over large directory table entry "
+ "%u>\n"), dir);
+ }
+ else
+ printf ("\n%s/%s:\n",
+ null_name (directory_table[dir]),
+ null_name (file_table[file].name));
+ }
+ }
break;
case DW_LNS_set_column:
uint64_t val;
READ_ULEB (val, data, end);
- printf ("0x%" PRIx64 "%s", val, i == 1 ? "" : ", ");
+ printf ("%#" PRIx64 "%s", val, i == 1 ? "" : ", ");
}
putchar ('\n');
break;
|| (xop == DW_LNS_copy))
{
const unsigned int MAX_FILENAME_LENGTH = 35;
- char *fileName;
+ char *fileName = NULL;
char *newFileName = NULL;
size_t fileNameLength;
/* PR 20439 */
if (indx >= n_files)
{
- warn (_("corrupt file index %u encountered\n"), indx);
+ warn (_("file index %u >= number of files %u\n"),
+ indx, n_files);
fileName = _("<corrupt>");
}
else
fileName = (char *) file_table[indx].name;
}
- else
+ if (!fileName)
fileName = _("<unknown>");
fileNameLength = strlen (fileName);
if (linfo.li_max_ops_per_insn == 1)
{
if (xop == -DW_LNE_end_sequence)
- printf ("%-35s %11s %#18" PRIx64,
+ printf ("%-31s %11s %#18" PRIx64,
newFileName, "-",
state_machine_regs.address);
else
- printf ("%-35s %11d %#18" PRIx64,
+ printf ("%-31s %11d %#18" PRIx64,
newFileName, state_machine_regs.line,
state_machine_regs.address);
}
else
{
if (xop == -DW_LNE_end_sequence)
- printf ("%-35s %11s %#18" PRIx64 "[%d]",
+ printf ("%-31s %11s %#18" PRIx64 "[%d]",
newFileName, "-",
state_machine_regs.address,
state_machine_regs.op_index);
else
- printf ("%-35s %11d %#18" PRIx64 "[%d]",
+ printf ("%-31s %11d %#18" PRIx64 "[%d]",
newFileName, state_machine_regs.line,
state_machine_regs.address,
state_machine_regs.op_index);
names.pn_length);
printf (_(" Version: %d\n"),
names.pn_version);
- printf (_(" Offset into .debug_info section: 0x%" PRIx64 "\n"),
+ printf (_(" Offset into .debug_info section: %#" PRIx64 "\n"),
names.pn_offset);
printf (_(" Size of area in .debug_info section: %" PRId64 "\n"),
names.pn_size);
SAFE_BYTE_GET_AND_INC (flags, curr, 1, end);
offset_size = (flags & 1) ? 8 : 4;
- printf (_(" Offset: 0x%" PRIx64 "\n"), sec_offset);
+ printf (_(" Offset: %#" PRIx64 "\n"), sec_offset);
printf (_(" Version: %d\n"), version);
printf (_(" Offset size: %d\n"), offset_size);
if (flags & 2)
{
SAFE_BYTE_GET_AND_INC (line_offset, curr, offset_size, end);
- printf (_(" Offset into .debug_line: 0x%" PRIx64 "\n"),
+ printf (_(" Offset into .debug_line: %#" PRIx64 "\n"),
line_offset);
}
if (flags & 4)
case DW_MACRO_import:
SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
- printf (_(" DW_MACRO_import - offset : 0x%" PRIx64 "\n"),
+ printf (_(" DW_MACRO_import - offset : %#" PRIx64 "\n"),
offset);
break;
READ_ULEB (lineno, curr, end);
SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
printf (_(" DW_MACRO_define_sup - lineno : %d"
- " macro offset : 0x%" PRIx64 "\n"),
+ " macro offset : %#" PRIx64 "\n"),
lineno, offset);
break;
READ_ULEB (lineno, curr, end);
SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
printf (_(" DW_MACRO_undef_sup - lineno : %d"
- " macro offset : 0x%" PRIx64 "\n"),
+ " macro offset : %#" PRIx64 "\n"),
lineno, offset);
break;
case DW_MACRO_import_sup:
SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
- printf (_(" DW_MACRO_import_sup - offset : 0x%" PRIx64 "\n"),
+ printf (_(" DW_MACRO_import_sup - offset : %#" PRIx64 "\n"),
offset);
break;
else
printf (" DW_MACRO_undef_strx ");
if (do_wide)
- printf (_("(with offset %" PRIx64 ") "), offset);
+ printf (_("(with offset %#" PRIx64 ") "), offset);
printf (_("lineno : %d macro : %s\n"),
lineno, string);
break;
break;
if (list->first_abbrev)
- printf (_(" Number TAG (0x%" PRIx64 ")\n"), offset);
+ printf (_(" Number TAG (%#" PRIx64 ")\n"), offset);
for (entry = list->first_abbrev; entry; entry = entry->next)
{
uint32_t i;
bool is_64bit;
- printf (_("Table at Offset 0x%tx\n"), start - section->start);
+ printf (_("Table at Offset %#tx\n"), start - section->start);
SAFE_BYTE_GET_AND_INC (length, start, 4, end);
if (length == 0xffffffff)
SAFE_BYTE_GET_AND_INC (segment_selector_size, start, 1, end);
SAFE_BYTE_GET_AND_INC (offset_entry_count, start, 4, end);
- printf (_(" Length: 0x%" PRIx64 "\n"), length);
+ printf (_(" Length: %#" PRIx64 "\n"), length);
printf (_(" DWARF version: %u\n"), version);
printf (_(" Address size: %u\n"), address_size);
printf (_(" Segment size: %u\n"), segment_selector_size);
return 0;
}
- printf (_("\n Offset Entries starting at 0x%tx:\n"),
+ printf (_("\n Offset Entries starting at %#tx:\n"),
start - section->start);
for (i = 0; i < offset_entry_count; i++)
uint64_t entry;
SAFE_BYTE_GET_AND_INC (entry, start, is_64bit ? 8 : 4, end);
- printf (_(" [%6u] 0x%" PRIx64 "\n"), i, entry);
+ printf (_(" [%6u] %#" PRIx64 "\n"), i, entry);
}
putchar ('\n');
const char *suffix = strrchr (section->name, '.');
bool is_dwo = false;
int is_loclists = strstr (section->name, "debug_loclists") != NULL;
- uint64_t expected_start = 0;
+ uint64_t header_size = 0;
if (suffix && strcmp (suffix, ".dwo") == 0)
is_dwo = true;
if (offset_entry_count != 0)
return display_offset_entry_loclists (section);
- expected_start = hdrptr - section_begin;
+ header_size = hdrptr - section_begin;
}
if (load_debug_info (file) == 0)
error (_("No location lists in .debug_info section!\n"));
if (debug_information [first].num_loc_offsets > 0
- && debug_information [first].loc_offsets [0] != expected_start
- && debug_information [first].loc_views [0] != expected_start)
+ && debug_information [first].loc_offsets [0] != header_size
+ && debug_information [first].loc_views [0] != header_size)
warn (_("Location lists in %s section start at %#" PRIx64
" rather than %#" PRIx64 "\n"),
section->name, debug_information [first].loc_offsets [0],
- expected_start);
+ header_size);
if (!locs_sorted)
array = (unsigned int *) xcmalloc (num_loc_list, sizeof (unsigned int));
printf (_(" Offset Begin End Expression\n"));
- seen_first_offset = 0;
for (i = first; i < num_debug_info_entries; i++)
{
- uint64_t offset, voffset;
+ uint64_t offset = 0, voffset = 0;
uint64_t base_address;
unsigned int k;
int has_frame_base;
sizeof (*array), loc_offsets_compar);
}
+ /* .debug_loclists has a per-unit header.
+ Update start if we are detecting it. */
+ if (debug_information [i].dwarf_version == 5)
+ {
+ j = locs_sorted ? 0 : array [0];
+
+ if (debug_information [i].num_loc_offsets)
+ offset = debug_information [i].loc_offsets [j];
+
+ if (debug_information [i].num_loc_views)
+ voffset = debug_information [i].loc_views [j];
+
+ /* Assume that the size of the header is constant across CUs. */
+ if (((start - section_begin) + header_size == offset)
+ || ((start -section_begin) + header_size == voffset))
+ start += header_size;
+ }
+
int adjacent_view_loclists = 1;
for (k = 0; k < debug_information [i].num_loc_offsets; k++)
{
start = vstart;
}
- if (!seen_first_offset || !adjacent_view_loclists)
- seen_first_offset = 1;
- else
+ if (start < next)
{
- if (start < next)
+ if (vnext && vnext < next)
warn (_("There is a hole [%#tx - %#" PRIx64 "]"
" in %s section.\n"),
- start - section_begin, offset, section->name);
- else if (start > next)
- warn (_("There is an overlap [%#tx - %#" PRIx64 "]"
+ start - section_begin, voffset, section->name);
+ else
+ warn (_("There is a hole [%#tx - %#" PRIx64 "]"
" in %s section.\n"),
start - section_begin, offset, section->name);
}
+ else if (start > next)
+ warn (_("There is an overlap [%#tx - %#" PRIx64 "]"
+ " in %s section.\n"),
+ start - section_begin, offset, section->name);
start = next;
vstart = vnext;
printf (_(" Length: %" PRId64 "\n"), arange.ar_length);
printf (_(" Version: %d\n"), arange.ar_version);
- printf (_(" Offset into .debug_info: 0x%" PRIx64 "\n"),
+ printf (_(" Offset into .debug_info: %#" PRIx64 "\n"),
arange.ar_info_offset);
printf (_(" Pointer Size: %d\n"), arange.ar_pointer_size);
printf (_(" Segment Size: %d\n"), arange.ar_segment_size);
end_ranges);
printf (" ");
print_hex (address, address_size);
- print_hex (length, address_size);
+ print_hex_ns (length, address_size);
putchar ('\n');
}
unsigned int idx;
unsigned int address_size = debug_addr_info [i]->pointer_size;
- printf (_(" For compilation unit at offset 0x%" PRIx64 ":\n"),
+ printf (_(" For compilation unit at offset %#" PRIx64 ":\n"),
debug_addr_info [i]->cu_offset);
printf (_("\tIndex\tAddress\n"));
SAFE_BYTE_GET_AND_INC (length, curr_header, 4, entry);
if (length == 0xffffffff)
SAFE_BYTE_GET_AND_INC (length, curr_header, 8, entry);
+ if (length > (size_t) (section->start + section->size - curr_header)
+ || length < (size_t) (entry - curr_header))
+ {
+ warn (_("Corrupt %s section: unit_length field of %#" PRIx64
+ " is invalid\n"), section->name, length);
+ return 0;
+ }
end = curr_header + length;
-
SAFE_BYTE_GET_AND_INC (version, curr_header, 2, entry);
if (version != 5)
warn (_("Corrupt %s section: expecting version number 5 in header but found %d instead\n"),
}
else
end = section->start + debug_addr_info [i + 1]->addr_base;
+
header = end;
idx = 0;
- while (entry < end)
+
+ if (address_size < 1 || address_size > sizeof (uint64_t))
+ {
+ warn (_("Corrupt %s section: address size (%x) is wrong"),
+ section->name, address_size);
+ return 0;
+ }
+
+ while ((size_t) (end - entry) >= address_size)
{
uint64_t base = byte_get (entry, address_size);
printf (_("\t%d:\t"), idx);
- print_hex (base, address_size);
+ print_hex_ns (base, address_size);
printf ("\n");
entry += address_size;
idx++;
}
print_hex (begin + base_address, pointer_size);
- print_hex (end + base_address, pointer_size);
+ print_hex_ns (end + base_address, pointer_size);
if (begin == end)
- fputs (_("(start == end)"), stdout);
+ fputs (_(" (start == end)"), stdout);
else if (begin > end)
- fputs (_("(start > end)"), stdout);
+ fputs (_(" (start > end)"), stdout);
putchar ('\n');
}
unsigned int pointer_size,
uint64_t offset,
uint64_t base_address,
- unsigned int offset_size)
+ uint64_t addr_base)
{
unsigned char *next = start;
- unsigned int debug_addr_section_hdr_len;
-
- if (offset_size == 4)
- debug_addr_section_hdr_len = 8;
- else
- debug_addr_section_hdr_len = 16;
while (1)
{
READ_ULEB (base_address, start, finish);
print_hex (base_address, pointer_size);
printf (_("(base address index) "));
- base_address = fetch_indexed_addr ((base_address * pointer_size)
- + debug_addr_section_hdr_len, pointer_size);
+ base_address = fetch_indexed_addr ((base_address * pointer_size) + addr_base,
+ pointer_size);
print_hex (base_address, pointer_size);
printf (_("(base address)\n"));
break;
case DW_RLE_startx_endx:
READ_ULEB (begin, start, finish);
READ_ULEB (end, start, finish);
- begin = fetch_indexed_addr ((begin * pointer_size)
- + debug_addr_section_hdr_len, pointer_size);
- end = fetch_indexed_addr ((begin * pointer_size)
- + debug_addr_section_hdr_len, pointer_size);
+ begin = fetch_indexed_addr ((begin * pointer_size) + addr_base,
+ pointer_size);
+ end = fetch_indexed_addr ((begin * pointer_size) + addr_base,
+ pointer_size);
break;
case DW_RLE_startx_length:
READ_ULEB (begin, start, finish);
READ_ULEB (length, start, finish);
- begin = fetch_indexed_addr ((begin * pointer_size)
- + debug_addr_section_hdr_len, pointer_size);
+ begin = fetch_indexed_addr ((begin * pointer_size) + addr_base,
+ pointer_size);
end = begin + length;
break;
case DW_RLE_offset_pair:
}
static int
-display_debug_rnglists (struct dwarf_section *section)
-{
- unsigned char *start = section->start;
- unsigned char *finish = start + section->size;
+display_debug_rnglists_unit_header (struct dwarf_section * section,
+ uint64_t * unit_offset,
+ unsigned char * poffset_size)
+{
+ uint64_t start_offset = *unit_offset;
+ unsigned char * p = section->start + start_offset;
+ unsigned char * finish = section->start + section->size;
+ uint64_t initial_length;
+ unsigned char segment_selector_size;
+ unsigned int offset_entry_count;
+ unsigned int i;
+ unsigned short version;
+ unsigned char address_size = 0;
+ unsigned char offset_size;
- while (start < finish)
- {
- unsigned char *table_start;
- uint64_t offset = start - section->start;
- unsigned char *end;
- uint64_t initial_length;
- unsigned char segment_selector_size;
- unsigned int offset_entry_count;
- unsigned int i;
- unsigned short version;
- unsigned char address_size = 0;
- unsigned char offset_size;
+ /* Get and check the length of the block. */
+ SAFE_BYTE_GET_AND_INC (initial_length, p, 4, finish);
- /* 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, p, 8, finish);
+ *poffset_size = offset_size = 8;
+ }
+ else
+ *poffset_size = offset_size = 4;
- if (initial_length == 0xffffffff)
- {
- /* This section is 64-bit DWARF 3. */
- SAFE_BYTE_GET_AND_INC (initial_length, start, 8, finish);
- offset_size = 8;
- }
+ if (initial_length > (size_t) (finish - p))
+ {
+ /* 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, (p - section->start) - offset_size))
+ initial_length = finish - p;
else
- offset_size = 4;
-
- if (initial_length > (size_t) (finish - start))
{
- /* 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;
- else
- {
- warn (_("The length field (%#" PRIx64
- ") in the debug_rnglists header is wrong"
- " - the section is too small\n"),
- initial_length);
- return 0;
- }
- }
-
- end = start + initial_length;
-
- /* Get the other fields in the header. */
- SAFE_BYTE_GET_AND_INC (version, start, 2, finish);
- SAFE_BYTE_GET_AND_INC (address_size, start, 1, finish);
- SAFE_BYTE_GET_AND_INC (segment_selector_size, start, 1, finish);
- SAFE_BYTE_GET_AND_INC (offset_entry_count, start, 4, finish);
-
- printf (_(" Table at Offset: 0x%" PRIx64 ":\n"), offset);
- printf (_(" Length: 0x%" PRIx64 "\n"), initial_length);
- printf (_(" DWARF version: %u\n"), version);
- printf (_(" Address size: %u\n"), address_size);
- printf (_(" Segment size: %u\n"), segment_selector_size);
- printf (_(" Offset entries: %u\n"), offset_entry_count);
-
- /* Check the fields. */
- if (segment_selector_size != 0)
- {
- warn (_("The %s section contains "
- "unsupported segment selector size: %d.\n"),
- section->name, segment_selector_size);
+ warn (_("The length field (%#" PRIx64
+ ") in the debug_rnglists header is wrong"
+ " - the section is too small\n"),
+ initial_length);
return 0;
}
+ }
- if (version < 5)
- {
- warn (_("Only DWARF version 5+ debug_rnglists info "
- "is currently supported.\n"));
- return 0;
- }
+ /* Report the next unit offset to the caller. */
+ *unit_offset = (p - section->start) + initial_length;
- table_start = start;
+ /* Get the other fields in the header. */
+ SAFE_BYTE_GET_AND_INC (version, p, 2, finish);
+ SAFE_BYTE_GET_AND_INC (address_size, p, 1, finish);
+ SAFE_BYTE_GET_AND_INC (segment_selector_size, p, 1, finish);
+ SAFE_BYTE_GET_AND_INC (offset_entry_count, p, 4, finish);
- if (offset_entry_count != 0)
- {
- printf (_("\n Offsets starting at 0x%tx:\n"),
- start - section->start);
+ printf (_(" Table at Offset: %#" PRIx64 ":\n"), start_offset);
+ printf (_(" Length: %#" PRIx64 "\n"), initial_length);
+ printf (_(" DWARF version: %u\n"), version);
+ printf (_(" Address size: %u\n"), address_size);
+ printf (_(" Segment size: %u\n"), segment_selector_size);
+ printf (_(" Offset entries: %u\n"), offset_entry_count);
- for (i = 0; i < offset_entry_count; i++)
- {
- uint64_t entry;
+ /* Check the fields. */
+ 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 (entry, start, offset_size, finish);
- printf (_(" [%6u] 0x%" PRIx64 "\n"), i, entry);
- }
- }
- else
- offset_entry_count = 1;
+ if (version < 5)
+ {
+ warn (_("Only DWARF version 5+ debug_rnglists info "
+ "is currently supported.\n"));
+ return 0;
+ }
+
+ if (offset_entry_count != 0)
+ {
+ printf (_("\n Offsets starting at %#tx:\n"), p - section->start);
for (i = 0; i < offset_entry_count; i++)
{
- uint64_t indx = start - table_start;
+ uint64_t entry;
- offset = start - section->start;
- printf (_("\n Offset: %" PRIx64 ", Index: 0x%" PRIx64 "\n"),
- offset, indx);
- printf (_(" Offset Begin End\n"));
- start = display_debug_rnglists_list
- (start, end, address_size, offset, 0, offset_size);
- if (start >= end)
- break;
+ SAFE_BYTE_GET_AND_INC (entry, p, offset_size, finish);
+ printf (_(" [%6u] %#" PRIx64 "\n"), i, entry);
}
-
- start = end;
-
- if (start < finish)
- putchar ('\n');
}
- putchar ('\n');
return 1;
}
+static bool
+is_range_list_for_this_section (bool is_rnglists, unsigned int version)
+{
+ if (is_rnglists && version > 4)
+ return true;
+
+ if (! is_rnglists && version < 5)
+ return true;
+
+ return false;
+}
+
static int
display_debug_ranges (struct dwarf_section *section,
void *file ATTRIBUTE_UNUSED)
unsigned int num_range_list, i;
struct range_entry *range_entries;
struct range_entry *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;
+ bool is_rnglists = strstr (section->name, "debug_rnglists") != NULL;
uint64_t last_offset = 0;
+ uint64_t next_rnglists_cu_offset = 0;
+ unsigned char offset_size;
if (bytes == 0)
{
}
introduce (section, false);
-
- if (is_rnglists)
- return display_debug_rnglists (section);
-
+
if (load_debug_info (file) == 0)
{
warn (_("Unable to load/parse the .debug_info section, so cannot interpret the %s section.\n"),
num_range_list = 0;
for (i = 0; i < num_debug_info_entries; i++)
- num_range_list += debug_information [i].num_range_lists;
+ if (is_range_list_for_this_section (is_rnglists, debug_information [i].dwarf_version))
+ 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"));
+ printf (_("No range lists referenced by .debug_info section.\n"));
return 1;
}
- range_entries = (struct range_entry *)
- xmalloc (sizeof (*range_entries) * num_range_list);
- range_entry_fill = range_entries;
+ range_entry_fill = range_entries = XNEWVEC (struct range_entry, num_range_list);
for (i = 0; i < num_debug_info_entries; i++)
{
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++;
+ if (is_range_list_for_this_section (is_rnglists, debug_info_p->dwarf_version))
+ {
+ range_entry_fill->ranges_offset = debug_info_p->range_lists[j];
+ range_entry_fill->debug_info_p = debug_info_p;
+ range_entry_fill++;
+ }
}
}
+ assert (range_entry_fill >= range_entries);
+ assert (num_range_list >= (unsigned int)(range_entry_fill - range_entries));
+ num_range_list = range_entry_fill - range_entries;
qsort (range_entries, num_range_list, sizeof (*range_entries),
range_entry_compar);
section->name, range_entries[0].ranges_offset);
putchar ('\n');
- printf (_(" Offset Begin End\n"));
+ if (!is_rnglists)
+ printf (_(" Offset Begin End\n"));
for (i = 0; i < num_range_list; i++)
{
unsigned char *next;
uint64_t base_address;
- pointer_size = (is_rnglists ? address_size : debug_info_p->pointer_size);
+ pointer_size = debug_info_p->pointer_size;
offset = range_entry->ranges_offset;
base_address = debug_info_p->base_address;
continue;
}
- next = section_begin + offset + debug_info_p->rnglists_base;
+ /* If we've moved on to the next compile unit in the rnglists section - dump the unit header(s). */
+ if (is_rnglists && next_rnglists_cu_offset < offset)
+ {
+ while (next_rnglists_cu_offset < offset)
+ display_debug_rnglists_unit_header (section, &next_rnglists_cu_offset, &offset_size);
+ printf (_(" Offset Begin End\n"));
+ }
+ next = section_begin + offset; /* Offset is from the section start, the base has already been added. */
+
/* If multiple DWARF entities reference the same range then we will
have multiple entries in the `range_entries' list for the same
offset. Thanks to the sort above these will all be consecutive in
start = next;
last_start = next;
- display_debug_ranges_list
- (start, finish, pointer_size, offset, base_address);
+ if (is_rnglists)
+ display_debug_rnglists_list
+ (start, finish, pointer_size, offset, base_address, debug_info_p->addr_base);
+ else
+ display_debug_ranges_list
+ (start, finish, pointer_size, offset, base_address);
}
+
+ /* Display trailing empty (or unreferenced) compile units, if any. */
+ if (is_rnglists)
+ while (next_rnglists_cu_offset < section->size)
+ display_debug_rnglists_unit_header (section, &next_rnglists_cu_offset, &offset_size);
+
putchar ('\n');
free (range_entries);
unsigned int ncols;
/* DW_CFA_{undefined,same_value,offset,register,unreferenced} */
short int *col_type;
- int *col_offset;
+ int64_t *col_offset;
char *augmentation;
unsigned int code_factor;
int data_factor;
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));
+ fc->col_type = xcrealloc (fc->col_type, fc->ncols,
+ sizeof (*fc->col_type));
+ fc->col_offset = xcrealloc (fc->col_offset, fc->ncols,
+ sizeof (*fc->col_offset));
/* PR 17512: file:002-10025-0.005. */
if (fc->col_type == NULL || fc->col_offset == NULL)
{
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 */
+ "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 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 64 - 71 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 72 - 79 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 80 - 87 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 88 - 95 */
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", /* 96 - 103 */
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", /* 104 - 111 */
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", /* 112 - 119 */
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", /* 120 - 127 */
};
/* A RISC-V replacement for REGNAME_INTERNAL_BY_TABLE_ONLY which handles
strcpy (tmp, "s");
break;
case DW_CFA_offset:
- sprintf (tmp, "c%+d", fc->col_offset[r]);
+ sprintf (tmp, "c%+" PRId64, fc->col_offset[r]);
break;
case DW_CFA_val_offset:
- sprintf (tmp, "v%+d", fc->col_offset[r]);
+ sprintf (tmp, "v%+" PRId64, fc->col_offset[r]);
break;
case DW_CFA_register:
sprintf (tmp, "%s", regname (fc->col_offset[r], 0));
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));
+ fc->col_type = xmalloc (sizeof (*fc->col_type));
+ fc->col_offset = xmalloc (sizeof (*fc->col_offset));
version = *start++;
if (!cie)
{
fc->ncols = 0;
- fc->col_type = (short int *) xmalloc (sizeof (short int));
- fc->col_offset = (int *) xmalloc (sizeof (int));
+ fc->col_type = xmalloc (sizeof (*fc->col_type));
+ fc->col_offset = xmalloc (sizeof (*fc->col_offset));
if (frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0) < 0)
{
warn (_("Invalid max register\n"));
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->col_type = xcmalloc (fc->ncols, sizeof (*fc->col_type));
+ fc->col_offset = xcmalloc (fc->ncols, sizeof (*fc->col_offset));
+ memcpy (fc->col_type, cie->col_type,
+ fc->ncols * sizeof (*fc->col_type));
+ memcpy (fc->col_offset, cie->col_offset,
+ fc->ncols * sizeof (*fc->col_offset));
fc->augmentation = cie->augmentation;
fc->ptr_size = cie->ptr_size;
eh_addr_size = cie->ptr_size;
while (start < block_end)
{
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;
- int64_t l;
+ int64_t sofs;
uint64_t ofs;
- uint64_t vma;
const char *reg_prefix = "";
op = *start++;
switch (op)
{
case DW_CFA_advance_loc:
+ opa *= fc->code_factor;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
- printf (" DW_CFA_advance_loc: %d to ",
- opa * fc->code_factor);
- print_hex_ns (fc->pc_begin + opa * fc->code_factor,
- fc->ptr_size);
+ printf (" DW_CFA_advance_loc: %d to ", opa);
+ print_hex_ns (fc->pc_begin + opa, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin += opa * fc->code_factor;
+ fc->pc_begin += opa;
break;
case DW_CFA_offset:
- READ_ULEB (roffs, start, block_end);
+ READ_ULEB (ofs, start, block_end);
+ ofs *= fc->data_factor;
if (opa >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
- printf (" DW_CFA_offset: %s%s at cfa%+ld\n",
- reg_prefix, regname (opa, 0),
- roffs * fc->data_factor);
+ printf (" DW_CFA_offset: %s%s at cfa%+" PRId64 "\n",
+ reg_prefix, regname (opa, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[opa] = DW_CFA_offset;
- fc->col_offset[opa] = roffs * fc->data_factor;
+ fc->col_offset[opa] = ofs;
}
break;
break;
case DW_CFA_set_loc:
- vma = get_encoded_value (&start, fc->fde_encoding, section,
+ ofs = get_encoded_value (&start, fc->fde_encoding, section,
block_end);
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
printf (" DW_CFA_set_loc: ");
- print_hex_ns (vma, fc->ptr_size);
+ print_hex_ns (ofs, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin = vma;
+ fc->pc_begin = ofs;
break;
case DW_CFA_advance_loc1:
SAFE_BYTE_GET_AND_INC (ofs, start, 1, block_end);
+ ofs *= fc->code_factor;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
- printf (" DW_CFA_advance_loc1: %" PRId64 " to ",
- ofs * fc->code_factor);
- print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
- fc->ptr_size);
+ printf (" DW_CFA_advance_loc1: %" PRId64 " to ", ofs);
+ print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin += ofs * fc->code_factor;
+ fc->pc_begin += ofs;
break;
case DW_CFA_advance_loc2:
SAFE_BYTE_GET_AND_INC (ofs, start, 2, block_end);
+ ofs *= fc->code_factor;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
- printf (" DW_CFA_advance_loc2: %" PRId64 " to ",
- ofs * fc->code_factor);
- print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
- fc->ptr_size);
+ printf (" DW_CFA_advance_loc2: %" PRId64 " to ", ofs);
+ print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin += ofs * fc->code_factor;
+ fc->pc_begin += ofs;
break;
case DW_CFA_advance_loc4:
SAFE_BYTE_GET_AND_INC (ofs, start, 4, block_end);
+ ofs *= fc->code_factor;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
- printf (" DW_CFA_advance_loc4: %" PRId64 " to ",
- ofs * fc->code_factor);
- print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
- fc->ptr_size);
+ printf (" DW_CFA_advance_loc4: %" PRId64 " to ", ofs);
+ print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin += ofs * fc->code_factor;
+ fc->pc_begin += ofs;
break;
case DW_CFA_offset_extended:
READ_ULEB (reg, start, block_end);
- READ_ULEB (roffs, start, block_end);
+ READ_ULEB (ofs, start, block_end);
+ ofs *= fc->data_factor;
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
- printf (" DW_CFA_offset_extended: %s%s at cfa%+ld\n",
- reg_prefix, regname (reg, 0),
- roffs * fc->data_factor);
+ printf (" DW_CFA_offset_extended: %s%s at cfa%+" PRId64 "\n",
+ reg_prefix, regname (reg, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = roffs * fc->data_factor;
+ fc->col_offset[reg] = ofs;
}
break;
case DW_CFA_val_offset:
READ_ULEB (reg, start, block_end);
- READ_ULEB (roffs, start, block_end);
+ READ_ULEB (ofs, start, block_end);
+ ofs *= fc->data_factor;
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
- printf (" DW_CFA_val_offset: %s%s is cfa%+ld\n",
- reg_prefix, regname (reg, 0),
- roffs * fc->data_factor);
+ printf (" DW_CFA_val_offset: %s%s is cfa%+" PRId64 "\n",
+ reg_prefix, regname (reg, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_val_offset;
- fc->col_offset[reg] = roffs * fc->data_factor;
+ fc->col_offset[reg] = ofs;
}
break;
case DW_CFA_register:
READ_ULEB (reg, start, block_end);
- READ_ULEB (roffs, start, block_end);
+ READ_ULEB (ofs, start, block_end);
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
{
printf (" DW_CFA_register: %s%s in ",
reg_prefix, regname (reg, 0));
- puts (regname (roffs, 0));
+ puts (regname (ofs, 0));
}
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_register;
- fc->col_offset[reg] = roffs;
+ fc->col_offset[reg] = ofs;
}
break;
rs->ra = fc->ra;
rs->cfa_exp = fc->cfa_exp;
rs->ncols = fc->ncols;
- rs->col_type = (short int *) xcmalloc (rs->ncols,
- sizeof (* rs->col_type));
- rs->col_offset = (int *) xcmalloc (rs->ncols, sizeof (* rs->col_offset));
- memcpy (rs->col_type, fc->col_type, rs->ncols * sizeof (* fc->col_type));
- memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (* fc->col_offset));
+ rs->col_type = xcmalloc (rs->ncols, sizeof (*rs->col_type));
+ rs->col_offset = xcmalloc (rs->ncols, sizeof (*rs->col_offset));
+ memcpy (rs->col_type, fc->col_type,
+ rs->ncols * sizeof (*fc->col_type));
+ memcpy (rs->col_offset, fc->col_offset,
+ rs->ncols * sizeof (*fc->col_offset));
rs->next = remembered_state;
remembered_state = rs;
break;
{
warn (_("Invalid column number in saved frame state\n"));
fc->ncols = 0;
- break;
}
- memcpy (fc->col_type, rs->col_type, rs->ncols * sizeof (* rs->col_type));
- memcpy (fc->col_offset, rs->col_offset,
- rs->ncols * sizeof (* rs->col_offset));
+ else
+ {
+ memcpy (fc->col_type, rs->col_type,
+ rs->ncols * sizeof (*rs->col_type));
+ memcpy (fc->col_offset, rs->col_offset,
+ rs->ncols * sizeof (*rs->col_offset));
+ }
free (rs->col_type);
free (rs->col_offset);
free (rs);
break;
case DW_CFA_def_cfa_expression:
- READ_ULEB (ul, start, block_end);
- if (ul > (size_t) (block_end - start))
+ READ_ULEB (ofs, start, block_end);
+ if (ofs > (size_t) (block_end - start))
{
- printf (_(" DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
+ printf (_(" %s: <corrupt len %" PRIu64 ">\n"),
+ "DW_CFA_def_cfa_expression", ofs);
break;
}
if (! do_debug_frames_interp)
{
printf (" DW_CFA_def_cfa_expression (");
decode_location_expression (start, eh_addr_size, 0, -1,
- ul, 0, section);
+ ofs, 0, section);
printf (")\n");
}
fc->cfa_exp = 1;
- start += ul;
+ start += ofs;
break;
case DW_CFA_expression:
READ_ULEB (reg, start, block_end);
- READ_ULEB (ul, start, block_end);
+ READ_ULEB (ofs, start, block_end);
if (reg >= fc->ncols)
reg_prefix = bad_reg;
/* PR 17512: file: 069-133014-0.006. */
/* PR 17512: file: 98c02eb4. */
- if (ul > (size_t) (block_end - start))
+ if (ofs > (size_t) (block_end - start))
{
- printf (_(" DW_CFA_expression: <corrupt len %lu>\n"), ul);
+ printf (_(" %s: <corrupt len %" PRIu64 ">\n"),
+ "DW_CFA_expression", ofs);
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);
+ ofs, 0, section);
printf (")\n");
}
if (*reg_prefix == '\0')
fc->col_type[reg] = DW_CFA_expression;
- start += ul;
+ start += ofs;
break;
case DW_CFA_val_expression:
READ_ULEB (reg, start, block_end);
- READ_ULEB (ul, start, block_end);
+ READ_ULEB (ofs, start, block_end);
if (reg >= fc->ncols)
reg_prefix = bad_reg;
- if (ul > (size_t) (block_end - start))
+ if (ofs > (size_t) (block_end - start))
{
- printf (" DW_CFA_val_expression: <corrupt len %lu>\n", ul);
+ printf (" %s: <corrupt len %" PRIu64 ">\n",
+ "DW_CFA_val_expression", ofs);
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);
+ ofs, 0, section);
printf (")\n");
}
if (*reg_prefix == '\0')
fc->col_type[reg] = DW_CFA_val_expression;
- start += ul;
+ start += ofs;
break;
case DW_CFA_offset_extended_sf:
READ_ULEB (reg, start, block_end);
- READ_SLEB (l, start, block_end);
+ READ_SLEB (sofs, start, block_end);
+ /* data_factor multiplicaton done here as unsigned to
+ avoid integer overflow warnings from asan on fuzzed
+ objects. */
+ ofs = sofs;
+ ofs *= fc->data_factor;
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_offset_extended_sf: %s%s at cfa%+" PRId64 "\n",
- reg_prefix, regname (reg, 0),
- l * fc->data_factor);
+ reg_prefix, regname (reg, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = l * fc->data_factor;
+ fc->col_offset[reg] = ofs;
}
break;
case DW_CFA_val_offset_sf:
READ_ULEB (reg, start, block_end);
- READ_SLEB (l, start, block_end);
+ READ_SLEB (sofs, start, block_end);
+ ofs = sofs;
+ ofs *= fc->data_factor;
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_val_offset_sf: %s%s is cfa%+" PRId64 "\n",
- reg_prefix, regname (reg, 0),
- l * fc->data_factor);
+ reg_prefix, regname (reg, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_val_offset;
- fc->col_offset[reg] = l * fc->data_factor;
+ fc->col_offset[reg] = ofs;
}
break;
case DW_CFA_def_cfa_sf:
READ_ULEB (fc->cfa_reg, start, block_end);
- READ_SLEB (l, start, block_end);
- l *= fc->data_factor;
- fc->cfa_offset = l;
+ READ_SLEB (sofs, start, block_end);
+ ofs = sofs;
+ ofs *= fc->data_factor;
+ fc->cfa_offset = ofs;
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_sf: %s ofs %" PRId64 "\n",
- regname (fc->cfa_reg, 0), l);
+ regname (fc->cfa_reg, 0), ofs);
break;
case DW_CFA_def_cfa_offset_sf:
- READ_SLEB (l, start, block_end);
- l *= fc->data_factor;
- fc->cfa_offset = l;
+ READ_SLEB (sofs, start, block_end);
+ ofs = sofs;
+ ofs *= fc->data_factor;
+ fc->cfa_offset = ofs;
if (! do_debug_frames_interp)
- printf (" DW_CFA_def_cfa_offset_sf: %" PRId64 "\n", l);
+ printf (" DW_CFA_def_cfa_offset_sf: %" PRId64 "\n", ofs);
break;
case DW_CFA_MIPS_advance_loc8:
SAFE_BYTE_GET_AND_INC (ofs, start, 8, block_end);
+ ofs *= fc->code_factor;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
- printf (" DW_CFA_MIPS_advance_loc8: %" PRId64 " to ",
- ofs * fc->code_factor);
- print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
- fc->ptr_size);
+ printf (" DW_CFA_MIPS_advance_loc8: %" PRId64 " to ", ofs);
+ print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin += ofs * fc->code_factor;
+ fc->pc_begin += ofs;
break;
case DW_CFA_GNU_window_save:
break;
case DW_CFA_GNU_args_size:
- READ_ULEB (ul, start, block_end);
+ READ_ULEB (ofs, start, block_end);
if (! do_debug_frames_interp)
- printf (" DW_CFA_GNU_args_size: %ld\n", ul);
+ printf (" DW_CFA_GNU_args_size: %" PRIu64 "\n", ofs);
break;
case DW_CFA_GNU_negative_offset_extended:
READ_ULEB (reg, start, block_end);
- READ_SLEB (l, start, block_end);
- l = - l;
+ READ_SLEB (sofs, start, block_end);
+ ofs = sofs;
+ ofs = -ofs * fc->data_factor;
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_GNU_negative_offset_extended: %s%s "
"at cfa%+" PRId64 "\n",
- reg_prefix, regname (reg, 0),
- l * fc->data_factor);
+ reg_prefix, regname (reg, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = l * fc->data_factor;
+ fc->col_offset[reg] = ofs;
}
break;
uint64_t cu_offset;
SAFE_BYTE_GET_AND_INC (cu_offset, hdrptr, offset_size, unit_end);
- printf ("[%3u] 0x%" PRIx64 "\n", i, cu_offset);
+ printf ("[%3u] %#" PRIx64 "\n", i, cu_offset);
}
putchar ('\n');
uint64_t tu_offset;
SAFE_BYTE_GET_AND_INC (tu_offset, hdrptr, offset_size, unit_end);
- printf ("[%3u] 0x%" PRIx64 "\n", i, tu_offset);
+ printf ("[%3u] %#" PRIx64 "\n", i, tu_offset);
}
putchar ('\n');
SAFE_BYTE_GET_AND_INC (signature, hdrptr, 8, unit_end);
printf (_("[%3u] "), i);
- print_hex (signature, 8);
+ print_hex_ns (signature, 8);
putchar ('\n');
}
putchar ('\n');
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;
+ uint32_t address_table_offset, symbol_table_offset, constant_pool_offset,
+ shortcut_table_offset;
unsigned int cu_list_elements, tu_list_elements;
unsigned int address_table_elements, symbol_table_slots;
unsigned char *cu_list, *tu_list;
- unsigned char *address_table, *symbol_table, *constant_pool;
+ unsigned char *address_table, *symbol_table, *shortcut_table, *constant_pool;
unsigned int i;
/* The documentation for the format of this file is in gdb/dwarf2read.c. */
introduce (section, false);
- if (section->size < 6 * sizeof (uint32_t))
+ version = section->size < 4 ? 0 : byte_get_little_endian (start, 4);
+ size_t header_size = (version < 9 ? 6 : 7) * sizeof (uint32_t);
+ if (section->size < header_size)
{
warn (_("Truncated header in the %s section.\n"), section->name);
return 0;
}
- version = byte_get_little_endian (start, 4);
printf (_("Version %lu\n"), (unsigned long) version);
/* Prior versions are obsolete, and future versions may not be
backwards compatible. */
- if (version < 3 || version > 8)
+ if (version < 3 || version > 9)
{
warn (_("Unsupported version %lu.\n"), (unsigned long) version);
return 0;
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);
+ shortcut_table_offset = byte_get_little_endian (start + 20, 4);
+ if (version < 9)
+ constant_pool_offset = shortcut_table_offset;
+ else
+ constant_pool_offset = byte_get_little_endian (start + 24, 4);
if (cu_list_offset > section->size
|| tu_list_offset > section->size
|| address_table_offset > section->size
|| symbol_table_offset > section->size
+ || shortcut_table_offset > section->size
|| constant_pool_offset > section->size
|| tu_list_offset < cu_list_offset
|| address_table_offset < tu_list_offset
|| symbol_table_offset < address_table_offset
- || constant_pool_offset < symbol_table_offset)
+ || shortcut_table_offset < symbol_table_offset
+ || constant_pool_offset < shortcut_table_offset)
{
warn (_("Corrupt header in the %s section.\n"), section->name);
return 0;
cu_list_elements = (tu_list_offset - cu_list_offset) / 16;
tu_list_elements = (address_table_offset - tu_list_offset) / 24;
address_table_elements = (symbol_table_offset - address_table_offset) / 20;
- symbol_table_slots = (constant_pool_offset - symbol_table_offset) / 8;
+ symbol_table_slots = (shortcut_table_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;
+ shortcut_table = start + shortcut_table_offset;
constant_pool = start + constant_pool_offset;
printf (_("\nCU table:\n"));
uint64_t cu_offset = byte_get_little_endian (cu_list + i * 16, 8);
uint64_t cu_length = byte_get_little_endian (cu_list + i * 16 + 8, 8);
- printf ("[%3u] 0x%" PRIx64 " - 0x%" PRIx64 "\n",
+ printf ("[%3u] %#" PRIx64 " - %#" PRIx64 "\n",
i, cu_offset, cu_offset + cu_length - 1);
}
uint64_t type_offset = byte_get_little_endian (tu_list + i * 24 + 8, 8);
uint64_t signature = byte_get_little_endian (tu_list + i * 24 + 16, 8);
- printf ("[%3u] 0x%" PRIx64 " 0x%" PRIx64 " ",
+ printf ("[%3u] %#" PRIx64 " %#" PRIx64 " ",
i, tu_offset, type_offset);
- print_hex (signature, 8);
+ print_hex_ns (signature, 8);
printf ("\n");
}
{
uint64_t low = byte_get_little_endian (address_table + i * 20, 8);
uint64_t high = byte_get_little_endian (address_table + i * 20 + 8, 8);
- uint32_t cu_index = byte_get_little_endian (address_table + i + 20 + 16, 4);
+ uint32_t cu_index = byte_get_little_endian (address_table + i * 20 + 16, 4);
print_hex (low, 8);
print_hex (high, 8);
}
}
+ if (version >= 9)
+ {
+ printf (_("\nShortcut table:\n"));
+
+ if (shortcut_table_offset + 8 > constant_pool_offset)
+ {
+ warn (_("Corrupt shortcut table in the %s section.\n"), section->name);
+ return 0;
+ }
+
+ uint32_t lang = byte_get_little_endian (shortcut_table, 4);
+ printf (_("Language of main: "));
+ display_lang (lang);
+ printf ("\n");
+
+ uint32_t name_offset = byte_get_little_endian (shortcut_table + 4, 4);
+ printf (_("Name of main: "));
+ if (name_offset >= section->size - constant_pool_offset)
+ {
+ printf (_("<corrupt offset: %x>\n"), name_offset);
+ warn (_("Corrupt name offset of 0x%x found for name of main\n"),
+ name_offset);
+ }
+ else
+ printf ("%s\n", constant_pool + name_offset);
+ }
+
return 1;
}
static void
prealloc_cu_tu_list (unsigned int nshndx)
{
+ if (nshndx == 0)
+ /* Always allocate at least one entry for the end-marker. */
+ nshndx = 1;
+
if (shndx_pool == NULL)
{
shndx_pool_size = nshndx;
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;
}
These sections are extensions for Fission.
See http://gcc.gnu.org/wiki/DebugFissionDWP. */
-static int
+static bool
process_cu_tu_index (struct dwarf_section *section, int do_display)
{
unsigned char *phdr = section->start;
if (phdr == NULL)
{
warn (_("Section %s is empty\n"), section->name);
- return 0;
+ return false;
}
/* 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;
+ return false;
}
phash = phdr;
"Section %s is too small for %u slots\n",
nslots),
section->name, nslots);
- return 0;
+ return false;
}
if (version == 1)
{
+ unsigned char *shndx_list;
+ unsigned int shndx;
+
if (!do_display)
- prealloc_cu_tu_list ((limit - ppool) / 4);
- for (i = 0; i < nslots; i++)
{
- unsigned char *shndx_list;
- unsigned int shndx;
-
- SAFE_BYTE_GET (signature, phash, 8, limit);
- if (signature != 0)
+ prealloc_cu_tu_list ((limit - ppool) / 4);
+ for (shndx_list = ppool + 4; shndx_list <= limit - 4; shndx_list += 4)
{
- SAFE_BYTE_GET (j, pindex, 4, limit);
- shndx_list = ppool + j * 4;
- /* PR 17531: file: 705e010d. */
- if (shndx_list < ppool)
- {
- warn (_("Section index pool located before start of section\n"));
- return 0;
- }
+ shndx = byte_get (shndx_list, 4);
+ add_shndx_to_cu_tu_entry (shndx);
+ }
+ end_cu_tu_entry ();
+ }
+ else
+ for (i = 0; i < nslots; i++)
+ {
+ SAFE_BYTE_GET (signature, phash, 8, limit);
+ if (signature != 0)
+ {
+ SAFE_BYTE_GET (j, pindex, 4, limit);
+ shndx_list = ppool + j * 4;
+ /* PR 17531: file: 705e010d. */
+ if (shndx_list < ppool)
+ {
+ warn (_("Section index pool located before start of section\n"));
+ return false;
+ }
- if (do_display)
- printf (_(" [%3d] Signature: 0x%" PRIx64 " Sections: "),
+ printf (_(" [%3d] Signature: %#" PRIx64 " Sections: "),
i, signature);
- for (;;)
- {
- if (shndx_list >= limit)
- {
- warn (_("Section %s too small for shndx pool\n"),
- section->name);
- return 0;
- }
- SAFE_BYTE_GET (shndx, shndx_list, 4, limit);
- if (shndx == 0)
- break;
- if (do_display)
+ for (;;)
+ {
+ if (shndx_list >= limit)
+ {
+ warn (_("Section %s too small for shndx pool\n"),
+ section->name);
+ return false;
+ }
+ SAFE_BYTE_GET (shndx, shndx_list, 4, limit);
+ if (shndx == 0)
+ break;
printf (" %d", shndx);
- else
- add_shndx_to_cu_tu_entry (shndx);
- shndx_list += 4;
- }
- if (do_display)
+ shndx_list += 4;
+ }
printf ("\n");
- else
- end_cu_tu_entry ();
- }
- phash += 8;
- pindex += 4;
- }
+ }
+ phash += 8;
+ pindex += 4;
+ }
}
else if (version == 2)
{
if (nused == -1u
|| _mul_overflow ((size_t) ncols, 4, &temp)
|| _mul_overflow ((size_t) nused + 1, temp, &total)
+ || total > (size_t) (limit - ppool)
+ /* PR 30227: ncols could be 0. */
+ || _mul_overflow ((size_t) nused + 1, 4, &total)
|| total > (size_t) (limit - ppool))
{
warn (_("Section %s too small for offset and size tables\n"),
section->name);
- return 0;
+ return false;
}
if (do_display)
{
warn (_("Row index (%u) is larger than number of used entries (%u)\n"),
row, nused);
- return 0;
+ return false;
}
if (!do_display)
prow = poffsets + (row - 1) * ncols * 4;
if (do_display)
- printf (" [%3d] 0x%" PRIx64, i, signature);
+ printf (" [%3d] %#" PRIx64, i, signature);
for (j = 0; j < ncols; j++)
{
unsigned char *p = prow + j * 4;
prow = psizes + (row - 1) * ncols * 4;
if (do_display)
- printf (" [%3d] 0x%" PRIx64, i, signature);
+ printf (" [%3d] %#" PRIx64, i, signature);
for (j = 0; j < ncols; j++)
{
printf ("\n");
warn (_("Too many rows/columns in DWARF index section %s\n"),
section->name);
- return 0;
+ return false;
}
SAFE_BYTE_GET (val, p, 4, limit);
if (do_display)
printf ("\n");
- return 1;
+ return true;
}
static int cu_tu_indexes_read = -1; /* Tri-state variable. */
Note: does *not* initialise the allocated memory to zero. */
void *
-cmalloc (size_t nmemb, size_t size)
+cmalloc (uint64_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
Note: does *not* initialise the allocated memory to zero. */
void *
-xcmalloc (size_t nmemb, size_t size)
+xcmalloc (uint64_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
{
fprintf (stderr,
- _("Attempt to allocate an array with an excessive number of elements: %#zx\n"),
+ _("Attempt to allocate an array with an excessive number of elements: %#" PRIx64 "\n"),
nmemb);
xexit (1);
}
Note: does *not* initialise any new memory to zero. */
void *
-xcrealloc (void *ptr, size_t nmemb, size_t size)
+xcrealloc (void *ptr, uint64_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
{
- error (_("Attempt to re-allocate an array with an excessive number of elements: %#zx\n"),
+ error (_("Attempt to re-allocate an array with an excessive number of elements: %#" PRIx64 "\n"),
nmemb);
xexit (1);
}
/* Like xcalloc, but verifies that the first parameter is not too large. */
void *
-xcalloc2 (size_t nmemb, size_t size)
+xcalloc2 (uint64_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
{
- error (_("Attempt to allocate a zero'ed array with an excessive number of elements: %#zx\n"),
+ error (_("Attempt to allocate a zero'ed array with an excessive number of elements: %#" PRIx64 "\n"),
nmemb);
xexit (1);
}
if (build_id_size > (section->size - 16))
{
- warn (_(".note.gnu.build-id data size is too bug\n"));
+ warn (_(".note.gnu.build-id data size is too big\n"));
return;
}
if (debug_information != NULL)
{
for (i = 0; i < alloc_num_debug_info_entries; i++)
- {
- if (debug_information [i].max_loc_offsets)
- {
- free (debug_information [i].loc_offsets);
- free (debug_information [i].have_frame_base);
- }
- if (debug_information [i].max_range_lists)
- free (debug_information [i].range_lists);
- }
+ free_debug_information (&debug_information[i]);
free (debug_information);
debug_information = NULL;
alloc_num_debug_info_entries = num_debug_info_entries = 0;