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
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
- {
- pointer_size = 4;
- bias = 12;
- }
-
- 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
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,
{
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 || 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
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);
- svalue = uvalue;
- if (svalue < 0)
- {
- warn (_("CU @ %#" PRIx64 " has has a negative rnglists_base "
- "value of %#" PRIx64 " - treating as zero"),
- debug_info_p->cu_offset, svalue);
- uvalue = 0;
- }
- 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)
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];
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:
debug_info_p->range_lists = (uint64_t *)
xcrealloc (debug_info_p->range_lists,
lmax, sizeof (*debug_info_p->range_lists));
- debug_info_p->range_versions = (unsigned int *)
- xcrealloc (debug_info_p->range_versions,
- lmax, sizeof (*debug_info_p->range_versions));
debug_info_p->max_range_lists = lmax;
}
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->range_versions [num] = dwarf_version;
debug_info_p->num_range_lists++;
}
break;
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:
}
if (ent->max_range_lists)
{
- free (ent->range_versions);
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.
}
}
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)
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: %#" PRIx64 ":\n"), 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);
-
- /* 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 %#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] %#" 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: %#" 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;
}
struct range_entry *range_entries;
struct range_entry *range_entry_fill;
bool is_rnglists = strstr (section->name, "debug_rnglists") != NULL;
- /* Initialize it due to a false compiler warning. */
- unsigned char address_size = 0;
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)
{
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++)
{
- if (is_range_list_for_this_section (is_rnglists, debug_info_p->range_versions[j]))
+ 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;
}
}
+ 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
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 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"));
}
}
+ 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;
}