static const char *regname_internal_by_table_only (unsigned int regno);
static int have_frame_base;
+static int frame_base_level = -1; /* To support nested DW_TAG_subprogram's. */
static int need_base_address;
static unsigned int num_debug_info_entries = 0;
if (form == DW_FORM_loclistx)
{
- if (debug_info_p == NULL )
- idx = (uint64_t) -1;
- else if (dwo)
+ if (dwo)
{
idx = fetch_indexed_offset (uvalue, loclists_dwo,
debug_info_p->loclists_base,
if (idx != (uint64_t) -1)
idx += (offset_size == 8) ? 20 : 12;
}
- else if (dwarf_version > 4)
+ else if (debug_info_p == NULL || dwarf_version > 4)
{
idx = fetch_indexed_offset (uvalue, loclists,
debug_info_p->loclists_base,
}
else if (form == DW_FORM_rnglistx)
{
- if (debug_info_p == NULL)
- idx = (uint64_t) -1;
+ if (dwo)
+ {
+ idx = fetch_indexed_offset (uvalue, rnglists,
+ debug_info_p->rnglists_base,
+ debug_info_p->offset_size);
+ }
else
- idx = fetch_indexed_offset (uvalue, rnglists,
- debug_info_p->rnglists_base,
- debug_info_p->offset_size);
+ {
+ if (debug_info_p == NULL)
+ base = 0;
+ else
+ base = debug_info_p->rnglists_base;
+ idx = fetch_indexed_offset (uvalue, rnglists, base,
+ debug_info_p->offset_size);
+ }
}
else
{
break;
case DW_AT_frame_base:
+ /* This is crude; the have_frame_base is reset on the next
+ subprogram, not at the end of the current topmost one. */
have_frame_base = 1;
+ frame_base_level = level;
/* Fall through. */
case DW_AT_location:
case DW_AT_GNU_locviews:
debug_info_p->have_frame_base [num] = have_frame_base;
if (attribute != DW_AT_GNU_locviews)
{
- uvalue += debug_info_p->loclists_base;
-
/* Corrupt DWARF info can produce more offsets than views.
See PR 23062 for an example. */
if (debug_info_p->num_loc_offsets
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)
+ else if (attr->attribute == DW_AT_addr_base || attr->attribute == DW_AT_GNU_addr_base)
{
if (attr->form == DW_FORM_sec_offset)
{
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);
+ data = skip_attribute (attr->form, data, end, pointer_size,
+ offset_size, dwarf_version);
}
}
need_dwo_info = do_loc;
break;
case DW_TAG_entry_point:
- case DW_TAG_subprogram:
need_base_address = 0;
/* Assuming that there is no DW_AT_frame_base. */
have_frame_base = 0;
break;
+ case DW_TAG_subprogram:
+ need_base_address = 0;
+ if (level <= frame_base_level)
+ /* Don't reset that for nested subprogram. */
+ have_frame_base = 0;
+ break;
}
debug_info *debug_info_p =
|| (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.
+ /* 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. */
+ 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;
break;
case -1:
- warn(_("DIE has locviews without loclist\n"));
+ warn (_("DIE has locviews without loclist\n"));
debug_info_p->num_loc_views--;
break;
static void
display_loclists_list (struct dwarf_section * section,
unsigned char ** start_ptr,
- unsigned int debug_info_entry,
+ debug_info * debug_info_p,
uint64_t offset,
uint64_t base_address,
unsigned char ** vstart_ptr,
unsigned int pointer_size;
unsigned int offset_size;
unsigned int dwarf_version;
+ uint64_t index;
/* Initialize it due to a false compiler warning. */
uint64_t begin = -1, vbegin = -1;
uint64_t length;
int need_frame_base;
- if (debug_info_entry >= num_debug_info_entries)
- {
- warn (_("No debug information available for "
- "loclists lists of entry: %u\n"),
- debug_info_entry);
- return;
- }
-
- cu_offset = debug_information [debug_info_entry].cu_offset;
- pointer_size = debug_information [debug_info_entry].pointer_size;
- offset_size = debug_information [debug_info_entry].offset_size;
- dwarf_version = debug_information [debug_info_entry].dwarf_version;
+ cu_offset = debug_info_p->cu_offset;
+ pointer_size = debug_info_p->pointer_size;
+ offset_size = debug_info_p->offset_size;
+ dwarf_version = debug_info_p->dwarf_version;
if (pointer_size < 2 || pointer_size > 8)
{
warn (_("Invalid pointer size (%d) in debug info for entry %d\n"),
- pointer_size, debug_info_entry);
+ pointer_size, (int)(debug_info_p - debug_information));
return;
}
break;
case DW_LLE_base_addressx:
- READ_ULEB (base_address, start, section_end);
- print_hex (base_address, pointer_size);
+ READ_ULEB (index, start, section_end);
+ print_hex (index, pointer_size);
printf (_("(index into .debug_addr) "));
- base_address = fetch_indexed_addr (base_address, pointer_size);
+ base_address = fetch_indexed_addr
+ (debug_info_p->addr_base + index * pointer_size, pointer_size);
print_hex (base_address, pointer_size);
printf (_("(base address)\n"));
break;
case DW_LLE_startx_endx:
- READ_ULEB (begin, start, section_end);
- begin = fetch_indexed_addr (begin, pointer_size);
- READ_ULEB (end, start, section_end);
- end = fetch_indexed_addr (end, pointer_size);
+ READ_ULEB (index, start, section_end);
+ begin = fetch_indexed_addr
+ (debug_info_p->addr_base + index * pointer_size, pointer_size);
+ READ_ULEB (index, start, section_end);
+ end = fetch_indexed_addr
+ (debug_info_p->addr_base + index * pointer_size, pointer_size);
break;
case DW_LLE_startx_length:
- READ_ULEB (begin, start, section_end);
- begin = fetch_indexed_addr (begin, pointer_size);
+ READ_ULEB (index, start, section_end);
+ begin = fetch_indexed_addr
+ (debug_info_p->addr_base + index * pointer_size, pointer_size);
READ_ULEB (end, start, section_end);
end += begin;
break;
return ret;
}
-static int
-display_offset_entry_loclists (struct dwarf_section *section)
+/* Reads and dumps the DWARFv5 loclists compiler unit header,
+ including the offset table.
+ Returns the offset of the next compile unit header. */
+
+static uint64_t
+display_loclists_unit_header (struct dwarf_section * section,
+ uint64_t header_offset,
+ uint32_t * offset_count,
+ unsigned char ** loclists_start)
{
- unsigned char * start = section->start;
- unsigned char * const end = start + section->size;
+ uint64_t length;
+ unsigned char *start = section->start + header_offset;
+ unsigned char *end = section->start + section->size;
+ unsigned short version;
+ unsigned char address_size;
+ unsigned char segment_selector_size;
+ bool is_64bit;
+ uint32_t i;
- introduce (section, false);
+ printf (_("Table at Offset %#" PRIx64 "\n"), header_offset);
- do
+ SAFE_BYTE_GET_AND_INC (length, start, 4, end);
+ if (length == 0xffffffff)
{
- uint64_t length;
- unsigned short version;
- unsigned char address_size;
- unsigned char segment_selector_size;
- uint32_t offset_entry_count;
- uint32_t i;
- bool is_64bit;
-
- printf (_("Table at Offset %#tx\n"), start - section->start);
-
- SAFE_BYTE_GET_AND_INC (length, start, 4, end);
- if (length == 0xffffffff)
- {
- is_64bit = true;
- SAFE_BYTE_GET_AND_INC (length, start, 8, end);
- }
- else
- is_64bit = false;
-
- SAFE_BYTE_GET_AND_INC (version, start, 2, end);
- SAFE_BYTE_GET_AND_INC (address_size, start, 1, end);
- SAFE_BYTE_GET_AND_INC (segment_selector_size, start, 1, end);
- SAFE_BYTE_GET_AND_INC (offset_entry_count, start, 4, end);
-
- 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);
- printf (_(" Offset entries: %u\n"), offset_entry_count);
+ is_64bit = true;
+ SAFE_BYTE_GET_AND_INC (length, start, 8, end);
+ }
+ else
+ is_64bit = false;
- if (version < 5)
- {
- warn (_("The %s section contains a corrupt or "
- "unsupported version number: %d.\n"),
- section->name, version);
- return 0;
- }
+ SAFE_BYTE_GET_AND_INC (version, start, 2, end);
+ SAFE_BYTE_GET_AND_INC (address_size, start, 1, end);
+ SAFE_BYTE_GET_AND_INC (segment_selector_size, start, 1, end);
+ SAFE_BYTE_GET_AND_INC (*offset_count, start, 4, end);
- if (segment_selector_size != 0)
- {
- warn (_("The %s section contains an "
- "unsupported segment selector size: %d.\n"),
- section->name, segment_selector_size);
- return 0;
- }
+ 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);
+ printf (_(" Offset entries: %u\n"), *offset_count);
- if (offset_entry_count == 0)
- {
- warn (_("The %s section contains a table without offset\n"),
- section->name);
- return 0;
- }
+ if (segment_selector_size != 0)
+ {
+ warn (_("The %s section contains an "
+ "unsupported segment selector size: %d.\n"),
+ section->name, segment_selector_size);
+ return (uint64_t)-1;
+ }
+ if ( *offset_count)
+ {
printf (_("\n Offset Entries starting at %#tx:\n"),
start - section->start);
- for (i = 0; i < offset_entry_count; i++)
+ for (i = 0; i < *offset_count; i++)
{
uint64_t entry;
SAFE_BYTE_GET_AND_INC (entry, start, is_64bit ? 8 : 4, end);
printf (_(" [%6u] %#" PRIx64 "\n"), i, entry);
}
-
- putchar ('\n');
-
- uint32_t j;
-
- for (j = 1, i = 0; i < offset_entry_count;)
- {
- unsigned char lle;
- uint64_t base_address = 0;
- uint64_t begin;
- uint64_t finish;
- uint64_t off = start - section->start;
-
- if (j != i)
- {
- printf (_(" Offset Entry %u\n"), i);
- j = i;
- }
-
- printf (" ");
- print_hex (off, 4);
-
- SAFE_BYTE_GET_AND_INC (lle, start, 1, end);
-
- switch (lle)
- {
- case DW_LLE_end_of_list:
- printf (_("<End of list>\n\n"));
- i ++;
- continue;
-
- case DW_LLE_base_addressx:
- READ_ULEB (base_address, start, end);
- print_hex (base_address, address_size);
- printf (_("(index into .debug_addr) "));
- base_address = fetch_indexed_addr (base_address, address_size);
- print_hex (base_address, address_size);
- printf (_("(base address)\n"));
- continue;
-
- case DW_LLE_startx_endx:
- READ_ULEB (begin, start, end);
- begin = fetch_indexed_addr (begin, address_size);
- READ_ULEB (finish, start, end);
- finish = fetch_indexed_addr (finish, address_size);
- break;
-
- case DW_LLE_startx_length:
- READ_ULEB (begin, start, end);
- begin = fetch_indexed_addr (begin, address_size);
- READ_ULEB (finish, start, end);
- finish += begin;
- break;
-
- case DW_LLE_offset_pair:
- READ_ULEB (begin, start, end);
- begin += base_address;
- READ_ULEB (finish, start, end);
- finish += base_address;
- break;
-
- case DW_LLE_default_location:
- begin = finish = 0;
- break;
-
- case DW_LLE_base_address:
- SAFE_BYTE_GET_AND_INC (base_address, start, address_size, end);
- print_hex (base_address, address_size);
- printf (_("(base address)\n"));
- continue;
-
- case DW_LLE_start_end:
- SAFE_BYTE_GET_AND_INC (begin, start, address_size, end);
- SAFE_BYTE_GET_AND_INC (finish, start, address_size, end);
- break;
-
- case DW_LLE_start_length:
- SAFE_BYTE_GET_AND_INC (begin, start, address_size, end);
- READ_ULEB (finish, start, end);
- finish += begin;
- break;
-
- default:
- error (_("Invalid location list entry type %d\n"), lle);
- return 0;
- }
-
- if (start == end)
- {
- warn (_("Location list starting at offset %#" PRIx64
- " is not terminated.\n"), off);
- break;
- }
-
- print_hex (begin, address_size);
- print_hex (finish, address_size);
-
- if (begin == finish)
- fputs (_("(start == end)"), stdout);
- else if (begin > finish)
- fputs (_("(start > end)"), stdout);
-
- /* Read the counted location descriptions. */
- READ_ULEB (length, start, end);
-
- if (length > (size_t) (end - start))
- {
- warn (_("Location list starting at offset %#" PRIx64
- " is not terminated.\n"), off);
- break;
- }
-
- (void) decode_location_expression (start, address_size, address_size,
- version, length, 0, section);
- start += length;
- putchar ('\n');
- }
-
- putchar ('\n');
}
- while (start < end);
- return 1;
+ putchar ('\n');
+ *loclists_start = start;
+
+ /* The length field doesn't include the length field itself. */
+ return header_offset + length + (is_64bit ? 12 : 4);
}
static int
const char *suffix = strrchr (section->name, '.');
bool is_dwo = false;
int is_loclists = strstr (section->name, "debug_loclists") != NULL;
- uint64_t header_size = 0;
+ uint64_t next_header_offset = 0;
if (suffix && strcmp (suffix, ".dwo") == 0)
is_dwo = true;
SAFE_BYTE_GET_AND_INC (offset_entry_count, hdrptr, 4, end);
- if (offset_entry_count != 0)
- return display_offset_entry_loclists (section);
+ /*if (offset_entry_count != 0)
+ return display_offset_entry_loclists (section);*/
- header_size = hdrptr - section_begin;
+ //header_size = hdrptr - section_begin;
}
if (load_debug_info (file) == 0)
if (!seen_first_offset)
error (_("No location lists in .debug_info section!\n"));
- if (debug_information [first].num_loc_offsets > 0
- && 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],
- header_size);
-
if (!locs_sorted)
array = (unsigned int *) xcmalloc (num_loc_list, sizeof (unsigned int));
if (reloc_at (section, 0))
printf (_(" Warning: This section has relocations - addresses seen here may not be accurate.\n\n"));
- printf (_(" Offset Begin End Expression\n"));
+ if (!is_loclists)
+ printf (_(" Offset Begin End Expression\n"));
for (i = first; i < num_debug_info_entries; i++)
{
uint64_t base_address;
unsigned int k;
int has_frame_base;
+ debug_info *debug_info_p = debug_information + i;
+ uint32_t offset_count;
+
if (!locs_sorted)
{
- for (k = 0; k < debug_information [i].num_loc_offsets; k++)
+ for (k = 0; k < debug_info_p->num_loc_offsets; k++)
array[k] = k;
- loc_offsets = debug_information [i].loc_offsets;
- loc_views = debug_information [i].loc_views;
- qsort (array, debug_information [i].num_loc_offsets,
+ loc_offsets = debug_info_p->loc_offsets;
+ loc_views = debug_info_p->loc_views;
+ qsort (array, debug_info_p->num_loc_offsets,
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)
+ if (debug_info_p->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_info_p->num_loc_offsets)
+ offset = debug_info_p->loc_offsets [j];
- if (debug_information [i].num_loc_views)
- voffset = debug_information [i].loc_views [j];
+ if (debug_info_p->num_loc_views)
+ voffset = debug_info_p->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;
+ /* Parse and dump unit headers in loclists.
+ This will misbehave if the order of CUs in debug_info
+ doesn't match the one in loclists. */
+ if (next_header_offset < offset)
+ {
+ while (next_header_offset < offset)
+ {
+ next_header_offset = display_loclists_unit_header
+ (section, next_header_offset, &offset_count, &start);
+
+ if (next_header_offset == (uint64_t)-1)
+ /* Header parsing error. */
+ return 0;
+ }
+
+ printf (_("\
+ Offset Begin End Expression\n"));
+ }
}
int adjacent_view_loclists = 1;
- for (k = 0; k < debug_information [i].num_loc_offsets; k++)
+
+ for (k = 0; k < debug_info_p->num_loc_offsets; k++)
{
j = locs_sorted ? k : array[k];
if (k
- && (debug_information [i].loc_offsets [locs_sorted
+ && (debug_info_p->loc_offsets [locs_sorted
? k - 1 : array [k - 1]]
- == debug_information [i].loc_offsets [j])
- && (debug_information [i].loc_views [locs_sorted
+ == debug_info_p->loc_offsets [j])
+ && (debug_info_p->loc_views [locs_sorted
? k - 1 : array [k - 1]]
- == debug_information [i].loc_views [j]))
+ == debug_info_p->loc_views [j]))
continue;
- has_frame_base = debug_information [i].have_frame_base [j];
- offset = debug_information [i].loc_offsets [j];
+ has_frame_base = debug_info_p->have_frame_base [j];
+ offset = debug_info_p->loc_offsets [j];
next = section_begin + offset;
- voffset = debug_information [i].loc_views [j];
+ voffset = debug_info_p->loc_views [j];
if (voffset != (uint64_t) -1)
vnext = section_begin + voffset;
else
vnext = NULL;
- base_address = debug_information [i].base_address;
+ base_address = debug_info_p->base_address;
if (vnext && vnext < next)
{
if (is_dwo)
warn (_("DWO is not yet supported.\n"));
else
- display_loclists_list (section, &start, i, offset, base_address,
- &vstart, has_frame_base);
+ display_loclists_list (section, &start, debug_info_p, offset,
+ base_address, &vstart, has_frame_base);
}
/* FIXME: this arrangement is quite simplistic. Nothing
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,
- shortcut_table_offset;
+ uint32_t address_table_offset, symbol_table_offset, constant_pool_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, *shortcut_table, *constant_pool;
+ unsigned char *address_table, *symbol_table, *constant_pool;
unsigned int i;
/* The documentation for the format of this file is in gdb/dwarf2read.c. */
introduce (section, false);
- 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)
+ if (section->size < 6 * sizeof (uint32_t))
{
warn (_("Truncated header in the %s section.\n"), section->name);
return 0;
}
+ version = byte_get_little_endian (start, 4);
printf (_("Version %lu\n"), (unsigned long) version);
/* Prior versions are obsolete, and future versions may not be
backwards compatible. */
- if (version < 3 || version > 9)
+ if (version < 3 || version > 8)
{
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);
- 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);
+ constant_pool_offset = byte_get_little_endian (start + 20, 4);
if (cu_list_offset > section->size
|| tu_list_offset > section->size
|| address_table_offset > section->size
|| symbol_table_offset > section->size
- || 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
- || shortcut_table_offset < symbol_table_offset
- || constant_pool_offset < shortcut_table_offset)
+ || constant_pool_offset < symbol_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 = (shortcut_table_offset - symbol_table_offset) / 8;
+ symbol_table_slots = (constant_pool_offset - symbol_table_offset) / 8;
cu_list = start + cu_list_offset;
tu_list = start + tu_list_offset;
address_table = start + address_table_offset;
symbol_table = start + symbol_table_offset;
- 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");
-
- printf (_("Name of main: "));
- if (lang == 0)
- printf (_("<unknown>\n"));
- else
- {
- uint32_t name_offset = byte_get_little_endian (shortcut_table + 4, 4);
- 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;
}