/* dwarf.c -- display DWARF contents of a BFD binary file
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
+ Copyright (C) 2005-2020 Free Software Foundation, Inc.
This file is part of GNU Binutils.
#include "safe-ctype.h"
#include <assert.h>
+#ifdef HAVE_LIBDEBUGINFOD
+#include <elfutils/debuginfod.h>
+#endif
+
#undef MAX
#undef MIN
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
static const char *regname (unsigned int regno, int row);
+static const char *regname_internal_by_table_only (unsigned int regno);
static int have_frame_base;
static int need_base_address;
int do_debug_frames_interp;
int do_debug_macinfo;
int do_debug_str;
+int do_debug_str_offsets;
int do_debug_loc;
int do_gdb_index;
int do_trace_info;
int do_wide;
int do_debug_links;
int do_follow_links;
+bfd_boolean do_checks;
int dwarf_cutoff_level = -1;
unsigned long dwarf_start_die;
/* 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.
+ If STATUS_RETURN in not NULL, return with bit 0 (LSB) set if the
+ terminating byte was not found and with bit 1 set if the value
+ overflows a dwarf_vma.
No bytes will be read at address END or beyond. */
dwarf_vma
read_leb128 (unsigned char *data,
- unsigned int *length_return,
+ const unsigned char *const end,
bfd_boolean sign,
- const unsigned char * const end)
+ unsigned int *length_return,
+ int *status_return)
{
dwarf_vma result = 0;
unsigned int num_read = 0;
unsigned int shift = 0;
- unsigned char byte = 0;
+ int status = 1;
while (data < end)
{
- byte = *data++;
+ unsigned char byte = *data++;
+ bfd_boolean cont = (byte & 0x80) ? TRUE : FALSE;
+
+ byte &= 0x7f;
num_read++;
- result |= ((dwarf_vma) (byte & 0x7f)) << shift;
+ if (shift < sizeof (result) * 8)
+ {
+ result |= ((dwarf_vma) byte) << shift;
+ if (sign)
+ {
+ if ((((dwarf_signed_vma) result >> shift) & 0x7f) != byte)
+ /* Overflow. */
+ status |= 2;
+ }
+ else if ((result >> shift) != byte)
+ {
+ /* Overflow. */
+ status |= 2;
+ }
- shift += 7;
- if ((byte & 0x80) == 0)
- break;
+ shift += 7;
+ }
+ else if (byte != 0)
+ {
+ status |= 2;
+ }
- /* PR 17512: file: 0ca183b8.
- FIXME: Should we signal this error somehow ? */
- if (shift >= sizeof (result) * 8)
- break;
+ if (!cont)
+ {
+ status &= ~1;
+ if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
+ result |= -((dwarf_vma) 1 << shift);
+ break;
+ }
}
if (length_return != NULL)
*length_return = num_read;
-
- if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
- result |= -((dwarf_vma) 1 << shift);
+ if (status_return != NULL)
+ *status_return = status;
return result;
}
-/* Create a signed version to avoid painful typecasts. */
-static inline dwarf_signed_vma
-read_sleb128 (unsigned char * data,
- unsigned int * length_return,
- const unsigned char * const end)
-{
- return (dwarf_signed_vma) read_leb128 (data, length_return, TRUE, end);
-}
-
-static inline dwarf_vma
-read_uleb128 (unsigned char * data,
- unsigned int * length_return,
- const unsigned char * const end)
-{
- return read_leb128 (data, length_return, FALSE, end);
-}
-
-#define SKIP_ULEB() read_uleb128 (start, & length_return, end); start += length_return
-#define SKIP_SLEB() read_sleb128 (start, & length_return, end); start += length_return
-
-#define READ_ULEB(var) \
- do \
- { \
- dwarf_vma _val; \
- \
- (var) = _val = read_uleb128 (start, &length_return, end); \
- if ((var) != _val) \
- error (_("Internal error: %s:%d: LEB value (%s) " \
- "too large for containing variable\n"), \
- __FILE__, __LINE__, dwarf_vmatoa ("u", _val)); \
- start += length_return; \
- } \
- while (0)
-
-#define READ_SLEB(var) \
- do \
- { \
- dwarf_signed_vma _val; \
- \
- (var) = _val = read_sleb128 (start, &length_return, end); \
- if ((var) != _val) \
- error (_("Internal error: %s:%d: LEB value (%s) " \
- "too large for containing variable\n"), \
- __FILE__, __LINE__, dwarf_vmatoa ("d", _val)); \
- start += length_return; \
- } \
- while (0)
-
/* Read AMOUNT bytes from PTR and store them in VAL as an unsigned value.
Checks to make sure that the read will not reach or pass END
and that VAL is big enough to hold AMOUNT bytes. */
/* Handled an extend line op.
Returns the number of bytes read. */
-static int
+static size_t
process_extended_line_op (unsigned char * data,
int is_stmt,
unsigned char * end)
{
unsigned char op_code;
- unsigned int bytes_read;
- unsigned int len;
+ size_t len, header_len;
unsigned char *name;
unsigned char *orig_data = data;
- dwarf_vma adr;
+ dwarf_vma adr, val;
- len = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_ULEB (len, data, end);
+ header_len = data - orig_data;
- if (len == 0 || data == end || len > (uintptr_t) (end - data))
+ if (len == 0 || data == end || len > (size_t) (end - data))
{
warn (_("Badly formed extended line op encountered!\n"));
- return bytes_read;
+ return header_len;
}
- len += bytes_read;
op_code = *data++;
printf (_(" Extended opcode %d: "), op_code);
case DW_LNE_set_address:
/* PR 17512: file: 002-100480-0.004. */
- if (len - bytes_read - 1 > 8)
+ if (len - 1 > 8)
{
- warn (_("Length (%d) of DW_LNE_set_address op is too long\n"),
- len - bytes_read - 1);
+ warn (_("Length (%lu) of DW_LNE_set_address op is too long\n"),
+ (unsigned long) len - 1);
adr = 0;
}
else
- SAFE_BYTE_GET (adr, data, len - bytes_read - 1, end);
+ SAFE_BYTE_GET (adr, data, len - 1, end);
printf (_("set Address to 0x%s\n"), dwarf_vmatoa ("x", adr));
state_machine_regs.address = adr;
state_machine_regs.view = 0;
name = data;
l = strnlen ((char *) data, end - data);
- data += len + 1;
- printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
- printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
- printf ("%s\t", dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
+ data += l + 1;
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
printf ("%.*s\n\n", (int) l, name);
}
- if (((unsigned int) (data - orig_data) != len) || data == end)
+ if (((size_t) (data - orig_data) != len + header_len) || data == end)
warn (_("DW_LNE_define_file: Bad opcode length\n"));
break;
case DW_LNE_set_discriminator:
- printf (_("set Discriminator to %s\n"),
- dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
+ READ_ULEB (val, data, end);
+ printf (_("set Discriminator to %s\n"), dwarf_vmatoa ("u", val));
break;
/* HP extensions. */
break;
case DW_LNE_HP_source_file_correlation:
{
- unsigned char *edata = data + len - bytes_read - 1;
+ unsigned char *edata = data + len - 1;
printf ("DW_LNE_HP_source_file_correlation\n");
{
unsigned int opc;
- opc = read_uleb128 (data, & bytes_read, edata);
- data += bytes_read;
+ READ_ULEB (opc, data, edata);
switch (opc)
{
printf (" DW_LNE_HP_SFC_formfeed\n");
break;
case DW_LNE_HP_SFC_set_listing_line:
+ READ_ULEB (val, data, edata);
printf (" DW_LNE_HP_SFC_set_listing_line (%s)\n",
- dwarf_vmatoa ("u",
- read_uleb128 (data, & bytes_read, edata)));
- data += bytes_read;
+ dwarf_vmatoa ("u", val));
break;
case DW_LNE_HP_SFC_associate:
printf (" DW_LNE_HP_SFC_associate ");
- printf ("(%s",
- dwarf_vmatoa ("u",
- read_uleb128 (data, & bytes_read, edata)));
- data += bytes_read;
- printf (",%s",
- dwarf_vmatoa ("u",
- read_uleb128 (data, & bytes_read, edata)));
- data += bytes_read;
- printf (",%s)\n",
- dwarf_vmatoa ("u",
- read_uleb128 (data, & bytes_read, edata)));
- data += bytes_read;
+ READ_ULEB (val, data, edata);
+ printf ("(%s", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, edata);
+ printf (",%s", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, edata);
+ printf (",%s)\n", dwarf_vmatoa ("u", val));
break;
default:
printf (_(" UNKNOWN DW_LNE_HP_SFC opcode (%u)\n"), opc);
default:
{
- unsigned int rlen = len - bytes_read - 1;
+ unsigned int rlen = len - 1;
if (op_code >= DW_LNE_lo_user
/* The test against DW_LNW_hi_user is redundant due to
break;
}
- return len;
+ return len + header_len;
}
static const unsigned char *
enum dwarf_section_display_enum idx_sec_idx = dwo ? str_index_dwo : str_index;
struct dwarf_section *index_section = &debug_displays [idx_sec_idx].section;
struct dwarf_section *str_section = &debug_displays [str_sec_idx].section;
- dwarf_vma index_offset = idx * offset_size;
+ dwarf_vma index_offset;
dwarf_vma str_offset;
const char * ret;
+ unsigned char *curr = index_section->start;
+ const unsigned char *end = curr + index_section->size;
+ dwarf_vma length;
if (index_section->start == NULL)
return (dwo ? _("<no .debug_str_offsets.dwo section>")
: _("<no .debug_str_offsets section>"));
+ if (str_section->start == NULL)
+ return (dwo ? _("<no .debug_str.dwo section>")
+ : _("<no .debug_str section>"));
+
+ /* FIXME: We should cache the length... */
+ SAFE_BYTE_GET_AND_INC (length, curr, 4, end);
+ if (length == 0xffffffff)
+ {
+ if (offset_size != 8)
+ warn (_("Expected offset size of 8 but given %s"), dwarf_vmatoa ("x", offset_size));
+ SAFE_BYTE_GET_AND_INC (length, curr, 8, end);
+ }
+ else if (offset_size != 4)
+ {
+ warn (_("Expected offset size of 4 but given %s"), dwarf_vmatoa ("x", offset_size));
+ }
+
+ if (length == 0)
+ {
+ /* This is probably an old style .debug_str_offset section which
+ just contains offsets and no header (and the first offset is 0). */
+ curr = index_section->start;
+ length = index_section->size;
+ }
+ else
+ {
+ /* Skip the version and padding bytes.
+ We assume that they are correct. */
+ curr += 4;
+
+ /* FIXME: The code below assumes that there is only one table
+ in the .debug_str_offsets section, so check that now. */
+ if ((offset_size == 4 && curr + length < (end - 8))
+ || (offset_size == 8 && curr + length < (end - 16)))
+ {
+ warn (_("index table size is too small %s vs %s\n"),
+ dwarf_vmatoa ("x", length),
+ dwarf_vmatoa ("x", index_section->size));
+ return _("<table too small>");
+ }
+ }
+
+ index_offset = idx * offset_size;
+
if (this_set != NULL)
index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS];
- if (index_offset >= index_section->size)
+
+ if (index_offset >= length)
{
- warn (_("DW_FORM_GNU_str_index offset too big: %s\n"),
- dwarf_vmatoa ("x", index_offset));
+ warn (_("DW_FORM_GNU_str_index offset too big: %s vs %s\n"),
+ dwarf_vmatoa ("x", index_offset),
+ dwarf_vmatoa ("x", length));
return _("<index offset is too big>");
}
- if (str_section->start == NULL)
- return (dwo ? _("<no .debug_str.dwo section>")
- : _("<no .debug_str section>"));
-
- str_offset = byte_get (index_section->start + index_offset, offset_size);
+ str_offset = byte_get (curr + index_offset, offset_size);
str_offset -= str_section->address;
if (str_offset >= str_section->size)
{
/* FIXME: There are better and more efficient ways to handle
these structures. For now though, I just want something that
is simple to implement. */
+/* Records a single attribute in an abbrev. */
typedef struct abbrev_attr
{
- unsigned long attribute;
- unsigned long form;
- bfd_signed_vma implicit_const;
- struct abbrev_attr *next;
+ unsigned long attribute;
+ unsigned long form;
+ bfd_signed_vma implicit_const;
+ struct abbrev_attr * next;
}
abbrev_attr;
+/* Records a single abbrev. */
typedef struct abbrev_entry
{
- unsigned long entry;
- unsigned long tag;
- int children;
- struct abbrev_attr *first_attr;
- struct abbrev_attr *last_attr;
- struct abbrev_entry *next;
+ unsigned long number;
+ unsigned long tag;
+ int children;
+ struct abbrev_attr * first_attr;
+ struct abbrev_attr * last_attr;
+ struct abbrev_entry * next;
}
abbrev_entry;
-static abbrev_entry *first_abbrev = NULL;
-static abbrev_entry *last_abbrev = NULL;
+/* Records a set of abbreviations. */
+typedef struct abbrev_list
+{
+ abbrev_entry * first_abbrev;
+ abbrev_entry * last_abbrev;
+ dwarf_vma abbrev_base;
+ dwarf_vma abbrev_offset;
+ struct abbrev_list * next;
+ unsigned char * start_of_next_abbrevs;
+}
+abbrev_list;
+
+/* Records all the abbrevs found so far. */
+static struct abbrev_list * abbrev_lists = NULL;
+
+typedef struct abbrev_map
+{
+ dwarf_vma start;
+ dwarf_vma end;
+ abbrev_list * list;
+} abbrev_map;
+
+/* Maps between CU offsets and abbrev sets. */
+static abbrev_map * cu_abbrev_map = NULL;
+static unsigned long num_abbrev_map_entries = 0;
+static unsigned long next_free_abbrev_map_entry = 0;
+
+#define INITIAL_NUM_ABBREV_MAP_ENTRIES 8
+#define ABBREV_MAP_ENTRIES_INCREMENT 8
static void
-free_abbrevs (void)
+record_abbrev_list_for_cu (dwarf_vma start, dwarf_vma end, abbrev_list * list)
{
- abbrev_entry *abbrv;
+ if (cu_abbrev_map == NULL)
+ {
+ num_abbrev_map_entries = INITIAL_NUM_ABBREV_MAP_ENTRIES;
+ cu_abbrev_map = xmalloc (num_abbrev_map_entries * sizeof (* cu_abbrev_map));
+ }
+ else if (next_free_abbrev_map_entry == num_abbrev_map_entries)
+ {
+ num_abbrev_map_entries += ABBREV_MAP_ENTRIES_INCREMENT;
+ cu_abbrev_map = xrealloc (cu_abbrev_map, num_abbrev_map_entries * sizeof (* cu_abbrev_map));
+ }
+
+ cu_abbrev_map[next_free_abbrev_map_entry].start = start;
+ cu_abbrev_map[next_free_abbrev_map_entry].end = end;
+ cu_abbrev_map[next_free_abbrev_map_entry].list = list;
+ next_free_abbrev_map_entry ++;
+}
- for (abbrv = first_abbrev; abbrv;)
+static void
+free_all_abbrevs (void)
+{
+ abbrev_list * list;
+
+ for (list = abbrev_lists; list != NULL;)
{
- abbrev_entry *next_abbrev = abbrv->next;
- abbrev_attr *attr;
+ abbrev_list * next = list->next;
+ abbrev_entry * abbrv;
- for (attr = abbrv->first_attr; attr;)
+ for (abbrv = list->first_abbrev; abbrv != NULL;)
{
- abbrev_attr *next_attr = attr->next;
+ abbrev_entry * next_abbrev = abbrv->next;
+ abbrev_attr * attr;
+
+ for (attr = abbrv->first_attr; attr;)
+ {
+ abbrev_attr *next_attr = attr->next;
- free (attr);
- attr = next_attr;
+ free (attr);
+ attr = next_attr;
+ }
+
+ free (abbrv);
+ abbrv = next_abbrev;
}
- free (abbrv);
- abbrv = next_abbrev;
+ free (list);
+ list = next;
}
- last_abbrev = first_abbrev = NULL;
+ abbrev_lists = NULL;
+}
+
+static abbrev_list *
+new_abbrev_list (dwarf_vma abbrev_base, dwarf_vma abbrev_offset)
+{
+ abbrev_list * list = (abbrev_list *) xcalloc (sizeof * list, 1);
+
+ list->abbrev_base = abbrev_base;
+ list->abbrev_offset = abbrev_offset;
+
+ list->next = abbrev_lists;
+ abbrev_lists = list;
+
+ return list;
+}
+
+static abbrev_list *
+find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base,
+ dwarf_vma abbrev_offset)
+{
+ abbrev_list * list;
+
+ for (list = abbrev_lists; list != NULL; list = list->next)
+ if (list->abbrev_base == abbrev_base
+ && list->abbrev_offset == abbrev_offset)
+ return list;
+
+ return NULL;
+}
+
+/* Find the abbreviation map for the CU that includes OFFSET.
+ OFFSET is an absolute offset from the start of the .debug_info section. */
+/* FIXME: This function is going to slow down readelf & objdump.
+ Consider using a better algorithm to mitigate this effect. */
+
+static abbrev_map *
+find_abbrev_map_by_offset (dwarf_vma offset)
+{
+ unsigned long i;
+
+ for (i = 0; i < next_free_abbrev_map_entry; i++)
+ if (cu_abbrev_map[i].start <= offset
+ && cu_abbrev_map[i].end > offset)
+ return cu_abbrev_map + i;
+
+ return NULL;
}
static void
-add_abbrev (unsigned long number, unsigned long tag, int children)
+add_abbrev (unsigned long number,
+ unsigned long tag,
+ int children,
+ abbrev_list * list)
{
- abbrev_entry *entry;
+ abbrev_entry * entry;
- entry = (abbrev_entry *) malloc (sizeof (*entry));
- if (entry == NULL)
- /* ugg */
- return;
+ entry = (abbrev_entry *) xmalloc (sizeof (*entry));
- entry->entry = number;
+ entry->number = number;
entry->tag = tag;
entry->children = children;
entry->first_attr = NULL;
entry->last_attr = NULL;
entry->next = NULL;
- if (first_abbrev == NULL)
- first_abbrev = entry;
+ assert (list != NULL);
+
+ if (list->first_abbrev == NULL)
+ list->first_abbrev = entry;
else
- last_abbrev->next = entry;
+ list->last_abbrev->next = entry;
- last_abbrev = entry;
+ list->last_abbrev = entry;
}
static void
-add_abbrev_attr (unsigned long attribute, unsigned long form,
- bfd_signed_vma implicit_const)
+add_abbrev_attr (unsigned long attribute,
+ unsigned long form,
+ bfd_signed_vma implicit_const,
+ abbrev_list * list)
{
abbrev_attr *attr;
- attr = (abbrev_attr *) malloc (sizeof (*attr));
- if (attr == NULL)
- /* ugg */
- return;
+ attr = (abbrev_attr *) xmalloc (sizeof (*attr));
attr->attribute = attribute;
attr->form = form;
attr->implicit_const = implicit_const;
attr->next = NULL;
- if (last_abbrev->first_attr == NULL)
- last_abbrev->first_attr = attr;
+ assert (list != NULL && list->last_abbrev != NULL);
+
+ if (list->last_abbrev->first_attr == NULL)
+ list->last_abbrev->first_attr = attr;
else
- last_abbrev->last_attr->next = attr;
+ list->last_abbrev->last_attr->next = attr;
- last_abbrev->last_attr = attr;
+ list->last_abbrev->last_attr = attr;
}
/* Processes the (partial) contents of a .debug_abbrev section.
an abbreviation set was found. */
static unsigned char *
-process_abbrev_section (unsigned char *start, unsigned char *end)
+process_abbrev_set (unsigned char * start,
+ const unsigned char * end,
+ abbrev_list * list)
{
- if (first_abbrev != NULL)
- return NULL;
-
while (start < end)
{
- unsigned int bytes_read;
unsigned long entry;
unsigned long tag;
unsigned long attribute;
int children;
- entry = read_uleb128 (start, & bytes_read, end);
- start += bytes_read;
+ READ_ULEB (entry, start, end);
- /* A single zero is supposed to end the section according
+ /* A single zero is supposed to end the set according
to the standard. If there's more, then signal that to
the caller. */
if (start == end)
if (entry == 0)
return start;
- tag = read_uleb128 (start, & bytes_read, end);
- start += bytes_read;
+ READ_ULEB (tag, start, end);
if (start == end)
return NULL;
children = *start++;
- add_abbrev (entry, tag, children);
+ add_abbrev (entry, tag, children, list);
do
{
/* Initialize it due to a false compiler warning. */
bfd_signed_vma implicit_const = -1;
- attribute = read_uleb128 (start, & bytes_read, end);
- start += bytes_read;
+ READ_ULEB (attribute, start, end);
if (start == end)
break;
- form = read_uleb128 (start, & bytes_read, end);
- start += bytes_read;
+ READ_ULEB (form, start, end);
if (start == end)
break;
if (form == DW_FORM_implicit_const)
{
- implicit_const = read_sleb128 (start, & bytes_read, end);
- start += bytes_read;
+ READ_SLEB (implicit_const, start, end);
if (start == end)
break;
}
- add_abbrev_attr (attribute, form, implicit_const);
+ add_abbrev_attr (attribute, form, implicit_const, list);
}
while (attribute != 0);
}
struct dwarf_section * section)
{
unsigned op;
- unsigned int bytes_read;
dwarf_vma uvalue;
dwarf_signed_vma svalue;
unsigned char *end = data + length;
printf ("%ld", (long) svalue);
break;
case DW_OP_constu:
- printf ("DW_OP_constu: %s",
- dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
+ printf ("DW_OP_constu: %s", dwarf_vmatoa ("u", uvalue));
break;
case DW_OP_consts:
- printf ("DW_OP_consts: %s",
- dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_SLEB (svalue, data, end);
+ printf ("DW_OP_consts: %s", dwarf_vmatoa ("d", svalue));
break;
case DW_OP_dup:
printf ("DW_OP_dup");
printf ("DW_OP_plus");
break;
case DW_OP_plus_uconst:
- printf ("DW_OP_plus_uconst: %s",
- dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
+ printf ("DW_OP_plus_uconst: %s", dwarf_vmatoa ("u", uvalue));
break;
case DW_OP_shl:
printf ("DW_OP_shl");
case DW_OP_breg29:
case DW_OP_breg30:
case DW_OP_breg31:
- printf ("DW_OP_breg%d (%s): %s",
- op - DW_OP_breg0,
- regname (op - DW_OP_breg0, 1),
- dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_SLEB (svalue, data, end);
+ printf ("DW_OP_breg%d (%s): %s", op - DW_OP_breg0,
+ regname (op - DW_OP_breg0, 1), dwarf_vmatoa ("d", svalue));
break;
case DW_OP_regx:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("DW_OP_regx: %s (%s)",
dwarf_vmatoa ("u", uvalue), regname (uvalue, 1));
break;
case DW_OP_fbreg:
need_frame_base = 1;
- printf ("DW_OP_fbreg: %s",
- dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_SLEB (svalue, data, end);
+ printf ("DW_OP_fbreg: %s", dwarf_vmatoa ("d", svalue));
break;
case DW_OP_bregx:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
+ READ_SLEB (svalue, data, end);
printf ("DW_OP_bregx: %s (%s) %s",
dwarf_vmatoa ("u", uvalue), regname (uvalue, 1),
- dwarf_vmatoa ("d", read_sleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ dwarf_vmatoa ("d", svalue));
break;
case DW_OP_piece:
- printf ("DW_OP_piece: %s",
- dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
+ printf ("DW_OP_piece: %s", dwarf_vmatoa ("u", uvalue));
break;
case DW_OP_deref_size:
SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
break;
case DW_OP_bit_piece:
printf ("DW_OP_bit_piece: ");
- printf (_("size: %s "),
- dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end)));
- data += bytes_read;
- printf (_("offset: %s "),
- dwarf_vmatoa ("u", read_uleb128 (data, &bytes_read, end)));
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
+ printf (_("size: %s "), dwarf_vmatoa ("u", uvalue));
+ READ_ULEB (uvalue, data, end);
+ printf (_("offset: %s "), dwarf_vmatoa ("u", uvalue));
break;
/* DWARF 4 extensions. */
case DW_OP_implicit_value:
printf ("DW_OP_implicit_value");
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
data = display_block (data, uvalue, end, ' ');
break;
{
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
}
+ READ_SLEB (svalue, data, end);
printf ("%s: <0x%s> %s",
(op == DW_OP_implicit_pointer
? "DW_OP_implicit_pointer" : "DW_OP_GNU_implicit_pointer"),
dwarf_vmatoa ("x", uvalue),
- dwarf_vmatoa ("d", read_sleb128 (data,
- &bytes_read, end)));
- data += bytes_read;
+ dwarf_vmatoa ("d", svalue));
break;
case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
/* PR 17531: file: 0cc9cd00. */
if (uvalue > (dwarf_vma) (end - data))
uvalue = end - data;
break;
case DW_OP_const_type:
case DW_OP_GNU_const_type:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("%s: <0x%s> ",
(op == DW_OP_const_type ? "DW_OP_const_type"
: "DW_OP_GNU_const_type"),
break;
case DW_OP_regval_type:
case DW_OP_GNU_regval_type:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("%s: %s (%s)",
(op == DW_OP_regval_type ? "DW_OP_regval_type"
: "DW_OP_GNU_regval_type"),
dwarf_vmatoa ("u", uvalue), regname (uvalue, 1));
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf (" <0x%s>", dwarf_vmatoa ("x", cu_offset + uvalue));
break;
case DW_OP_deref_type:
(op == DW_OP_deref_type ? "DW_OP_deref_type"
: "DW_OP_GNU_deref_type"),
(long) uvalue);
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf (" <0x%s>", dwarf_vmatoa ("x", cu_offset + uvalue));
break;
case DW_OP_convert:
case DW_OP_GNU_convert:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("%s <0x%s>",
(op == DW_OP_convert ? "DW_OP_convert" : "DW_OP_GNU_convert"),
dwarf_vmatoa ("x", uvalue ? cu_offset + uvalue : 0));
break;
case DW_OP_reinterpret:
case DW_OP_GNU_reinterpret:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("%s <0x%s>",
(op == DW_OP_reinterpret ? "DW_OP_reinterpret"
: "DW_OP_GNU_reinterpret"),
dwarf_vmatoa ("x", cu_offset + uvalue));
break;
case DW_OP_GNU_addr_index:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("DW_OP_GNU_addr_index <0x%s>", dwarf_vmatoa ("x", uvalue));
break;
case DW_OP_GNU_const_index:
- uvalue = read_uleb128 (data, &bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
printf ("DW_OP_GNU_const_index <0x%s>", dwarf_vmatoa ("x", uvalue));
break;
case DW_OP_GNU_variable_value:
int dwarf_version,
dwarf_vma * value_return)
{
- unsigned int bytes_read;
- dwarf_vma uvalue = 0;
+ dwarf_signed_vma svalue;
+ dwarf_vma uvalue = 0;
* value_return = 0;
case DW_FORM_ref_addr:
if (dwarf_version == 2)
SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
- else if (dwarf_version == 3 || dwarf_version == 4)
+ else if (dwarf_version > 2)
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
else
return NULL;
break;
case DW_FORM_sdata:
- uvalue = read_sleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_SLEB (svalue, data, end);
+ uvalue = svalue;
break;
case DW_FORM_ref_udata:
case DW_FORM_udata:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_addr_index:
- uvalue = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_ULEB (uvalue, data, end);
break;
case DW_FORM_ref8:
case DW_FORM_data8:
+ case DW_FORM_ref_sig8:
data += 8;
break;
case DW_FORM_block:
case DW_FORM_exprloc:
- uvalue = read_uleb128 (data, & bytes_read, end);
- data += bytes_read + uvalue;
+ READ_ULEB (uvalue, data, end);
+ data += uvalue;
break;
case DW_FORM_block1:
data += 4 + uvalue;
break;
- case DW_FORM_ref_sig8:
- data += 8;
- break;
-
case DW_FORM_indirect:
- /* FIXME: Handle this form. */
+ READ_ULEB (form, data, end);
+ if (form == DW_FORM_implicit_const)
+ SKIP_ULEB (data, end);
+ return skip_attr_bytes (form, data, end, pointer_size, offset_size, dwarf_version, value_return);
+
default:
return NULL;
}
return data;
}
-/* Return IS_SIGNED set to TRUE if the type at
- DATA can be determined to be a signed type. */
+/* Given form FORM with value UVALUE, locate and return the abbreviation
+ associated with it. */
+
+static abbrev_entry *
+get_type_abbrev_from_form (unsigned long form,
+ unsigned long uvalue,
+ dwarf_vma cu_offset,
+ const struct dwarf_section * section,
+ unsigned long * abbrev_num_return,
+ unsigned char ** data_return,
+ unsigned long * cu_offset_return)
+{
+ unsigned long abbrev_number;
+ abbrev_map * map;
+ abbrev_entry * entry;
+ unsigned char * data;
+
+ if (abbrev_num_return != NULL)
+ * abbrev_num_return = 0;
+ if (data_return != NULL)
+ * data_return = NULL;
+
+ switch (form)
+ {
+ case DW_FORM_GNU_ref_alt:
+ /* FIXME: We are unable to handle this form at the moment. */
+ return NULL;
+
+ case DW_FORM_ref_addr:
+ if (uvalue >= section->size)
+ {
+ warn (_("Unable to resolve ref_addr form: uvalue %lx > section size %lx (%s)\n"),
+ uvalue, (long) section->size, section->name);
+ return NULL;
+ }
+ break;
+
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref_udata:
+ if (uvalue + cu_offset > section->size)
+ {
+ warn (_("Unable to resolve ref form: uvalue %lx + cu_offset %lx > section size %lx\n"),
+ uvalue, (long) cu_offset, (long) section->size);
+ return NULL;
+ }
+ uvalue += cu_offset;
+ break;
+
+ /* FIXME: Are there other DW_FORMs that can be used by types ? */
+
+ default:
+ warn (_("Unexpected form %lx encountered whilst finding abbreviation for type\n"), form);
+ return NULL;
+ }
+
+ data = (unsigned char *) section->start + uvalue;
+ map = find_abbrev_map_by_offset (uvalue);
+
+ if (map == NULL)
+ {
+ warn (_("Unable to find abbreviations for CU offset %#lx\n"), uvalue);
+ return NULL;
+ }
+ if (map->list == NULL)
+ {
+ warn (_("Empty abbreviation list encountered for CU offset %lx\n"), uvalue);
+ return NULL;
+ }
+
+ if (cu_offset_return != NULL)
+ {
+ if (form == DW_FORM_ref_addr)
+ * cu_offset_return = map->start;
+ else
+ * cu_offset_return = cu_offset;
+ }
+
+ READ_ULEB (abbrev_number, data, section->start + section->size);
+
+ for (entry = map->list->first_abbrev; entry != NULL; entry = entry->next)
+ if (entry->number == abbrev_number)
+ break;
+
+ if (abbrev_num_return != NULL)
+ * abbrev_num_return = abbrev_number;
+
+ if (data_return != NULL)
+ * data_return = data;
+
+ if (entry == NULL)
+ warn (_("Unable to find entry for abbreviation %lu\n"), abbrev_number);
+
+ return entry;
+}
+
+/* Return IS_SIGNED set to TRUE if the type using abbreviation ENTRY
+ can be determined to be a signed type. The data for ENTRY can be
+ found starting at DATA. */
static void
-get_type_signedness (unsigned char * start,
+get_type_signedness (abbrev_entry * entry,
+ const struct dwarf_section * section,
unsigned char * data,
unsigned const char * end,
+ dwarf_vma cu_offset,
dwarf_vma pointer_size,
dwarf_vma offset_size,
int dwarf_version,
bfd_boolean * is_signed,
- bfd_boolean is_nested)
+ unsigned int nesting)
{
- unsigned long abbrev_number;
- unsigned int bytes_read;
- abbrev_entry * entry;
abbrev_attr * attr;
* is_signed = FALSE;
- abbrev_number = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
-
- for (entry = first_abbrev;
- entry != NULL && entry->entry != abbrev_number;
- entry = entry->next)
- continue;
-
- if (entry == NULL)
- /* FIXME: Issue a warning ? */
- return;
+#define MAX_NESTING 20
+ if (nesting > MAX_NESTING)
+ {
+ /* FIXME: Warn - or is this expected ?
+ NB/ We need to avoid infinite recursion. */
+ return;
+ }
for (attr = entry->first_attr;
attr != NULL && attr->attribute;
attr = attr->next)
{
+ unsigned char * orig_data = data;
dwarf_vma uvalue = 0;
data = skip_attr_bytes (attr->form, data, end, pointer_size,
switch (attr->attribute)
{
-#if 0 /* FIXME: It would be nice to print the name of the type,
- but this would mean updating a lot of binutils tests. */
+ case DW_AT_linkage_name:
case DW_AT_name:
- if (attr->form == DW_FORM_strp)
- printf ("%s", fetch_indirect_string (uvalue));
+ if (do_wide)
+ {
+ if (attr->form == DW_FORM_strp)
+ printf (", %s", fetch_indirect_string (uvalue));
+ else if (attr->form == DW_FORM_string)
+ printf (", %s", orig_data);
+ }
break;
-#endif
+
case DW_AT_type:
/* Recurse. */
- if (is_nested)
- {
- /* FIXME: Warn - or is this expected ?
- NB/ We need to avoid infinite recursion. */
- return;
- }
- if (uvalue >= (size_t) (end - start))
- return;
- get_type_signedness (start, start + uvalue, end, pointer_size,
- offset_size, dwarf_version, is_signed, TRUE);
+ {
+ abbrev_entry * type_abbrev;
+ unsigned char * type_data;
+ unsigned long type_cu_offset;
+
+ type_abbrev = get_type_abbrev_from_form (attr->form,
+ uvalue,
+ cu_offset,
+ section,
+ NULL /* abbrev num return */,
+ & type_data,
+ & type_cu_offset);
+ if (type_abbrev == NULL)
+ break;
+
+ get_type_signedness (type_abbrev, section, type_data, end, type_cu_offset,
+ pointer_size, offset_size, dwarf_version,
+ is_signed, nesting + 1);
+ }
break;
case DW_AT_encoding:
unsigned const char * end,
bfd_boolean is_signed)
{
- if (is_signed)
- {
- dwarf_signed_vma sval = read_sleb128 (data, bytes_read, end);
- printf ("%ld", (long) sval);
- }
+ int status;
+ dwarf_vma val = read_leb128 (data, end, is_signed, bytes_read, &status);
+ if (status != 0)
+ report_leb_status (status, __FILE__, __LINE__);
else
- {
- dwarf_vma uval = read_uleb128 (data, bytes_read, end);
- printf ("%lu", (unsigned long) uval);
- }
+ printf ("%s", dwarf_vmatoa (is_signed ? "d" : "u", val));
}
static void
char delimiter,
int level)
{
+ dwarf_signed_vma svalue;
dwarf_vma uvalue = 0;
unsigned char * block_start = NULL;
unsigned char * orig_data = data;
- unsigned int bytes_read;
if (data > end || (data == end && form != DW_FORM_flag_present))
{
case DW_FORM_ref_addr:
if (dwarf_version == 2)
SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
- else if (dwarf_version == 3 || dwarf_version == 4)
+ else if (dwarf_version > 2)
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
else
- error (_("Internal error: DWARF version is not 2, 3 or 4.\n"));
-
+ error (_("Internal error: DW_FORM_ref_addr is not supported in DWARF version 1.\n"));
break;
case DW_FORM_addr:
break;
case DW_FORM_sdata:
- uvalue = read_sleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_SLEB (svalue, data, end);
+ uvalue = svalue;
break;
case DW_FORM_GNU_str_index:
- uvalue = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- break;
-
case DW_FORM_ref_udata:
case DW_FORM_udata:
- uvalue = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ case DW_FORM_GNU_addr_index:
+ READ_ULEB (uvalue, data, end);
break;
case DW_FORM_indirect:
- form = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_ULEB (form, data, end);
if (!do_loc)
printf ("%c%s", delimiter, get_FORM_name (form));
if (form == DW_FORM_implicit_const)
- {
- implicit_const = read_sleb128 (data, & bytes_read, end);
- data += bytes_read;
- }
+ READ_SLEB (implicit_const, data, end);
return read_and_display_attr_value (attribute, form, implicit_const,
start, data, end,
cu_offset, pointer_size,
offset_size, dwarf_version,
debug_info_p, do_loc,
section, this_set, delimiter, level);
- case DW_FORM_GNU_addr_index:
- uvalue = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- break;
}
switch (form)
{
case DW_FORM_ref_addr:
if (!do_loc)
- printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x",uvalue));
+ printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue));
break;
case DW_FORM_GNU_ref_alt:
if (!do_loc)
- printf ("%c<alt 0x%s>", delimiter, dwarf_vmatoa ("x",uvalue));
+ printf ("%c<alt 0x%s>", delimiter, dwarf_vmatoa ("x", uvalue));
/* FIXME: Follow the reference... */
break;
case DW_FORM_block:
case DW_FORM_exprloc:
- uvalue = read_uleb128 (data, & bytes_read, end);
- block_start = data + bytes_read;
+ READ_ULEB (uvalue, data, end);
+ do_block:
+ block_start = data;
if (block_start >= end)
{
warn (_("Block ends prematurely\n"));
break;
case DW_FORM_block1:
- SAFE_BYTE_GET (uvalue, data, 1, end);
- block_start = data + 1;
- if (block_start >= end)
- {
- warn (_("Block ends prematurely\n"));
- uvalue = 0;
- block_start = end;
- }
-
- uvalue = check_uvalue (block_start, uvalue, end);
-
- if (do_loc)
- data = block_start + uvalue;
- else
- data = display_block (block_start, uvalue, end, delimiter);
- break;
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
+ goto do_block;
case DW_FORM_block2:
- SAFE_BYTE_GET (uvalue, data, 2, end);
- block_start = data + 2;
- if (block_start >= end)
- {
- warn (_("Block ends prematurely\n"));
- uvalue = 0;
- block_start = end;
- }
-
- uvalue = check_uvalue (block_start, uvalue, end);
-
- if (do_loc)
- data = block_start + uvalue;
- else
- data = display_block (block_start, uvalue, end, delimiter);
- break;
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
+ goto do_block;
case DW_FORM_block4:
- SAFE_BYTE_GET (uvalue, data, 4, end);
- block_start = data + 4;
- /* PR 17512: file: 3371-3907-0.004. */
- if (block_start >= end)
- {
- warn (_("Block ends prematurely\n"));
- uvalue = 0;
- block_start = end;
- }
-
- uvalue = check_uvalue (block_start, uvalue, end);
-
- if (do_loc)
- data = block_start + uvalue;
- else
- data = display_block (block_start, uvalue, end, delimiter);
- break;
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
+ goto do_block;
case DW_FORM_strp:
if (!do_loc)
case DW_FORM_strp:
add_dwo_name ((const char *) fetch_indirect_string (uvalue));
break;
+ case DW_FORM_GNU_strp_alt:
+ add_dwo_name ((const char *) fetch_alt_indirect_string (uvalue));
+ break;
case DW_FORM_GNU_str_index:
add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, FALSE));
break;
case DW_FORM_strp:
add_dwo_dir ((const char *) fetch_indirect_string (uvalue));
break;
+ case DW_FORM_GNU_strp_alt:
+ add_dwo_dir (fetch_alt_indirect_string (uvalue));
+ break;
case DW_FORM_line_strp:
add_dwo_dir ((const char *) fetch_indirect_line_string (uvalue));
break;
&& uvalue < (size_t) (end - start))
{
bfd_boolean is_signed = FALSE;
-
- get_type_signedness (start, start + uvalue, end, pointer_size,
- offset_size, dwarf_version, & is_signed, FALSE);
+ abbrev_entry * type_abbrev;
+ unsigned char * type_data;
+ unsigned long type_cu_offset;
+
+ type_abbrev = get_type_abbrev_from_form (form, uvalue, cu_offset,
+ section, NULL, & type_data, & type_cu_offset);
+ if (type_abbrev != NULL)
+ {
+ get_type_signedness (type_abbrev, section, type_data, end, type_cu_offset,
+ pointer_size, offset_size, dwarf_version,
+ & is_signed, 0);
+ }
level_type_signed[level] = is_signed;
}
break;
case DW_AT_import:
{
- if (form == DW_FORM_ref_sig8
- || form == DW_FORM_GNU_ref_alt)
- break;
-
- if (form == DW_FORM_ref1
- || form == DW_FORM_ref2
- || form == DW_FORM_ref4
- || form == DW_FORM_ref_udata)
- uvalue += cu_offset;
+ unsigned long abbrev_number;
+ abbrev_entry *entry;
- if (uvalue >= section->size)
- warn (_("Offset %s used as value for DW_AT_import attribute of DIE at offset 0x%lx is too big.\n"),
- dwarf_vmatoa ("x", uvalue),
- (unsigned long) (orig_data - section->start));
+ entry = get_type_abbrev_from_form (form, uvalue, cu_offset,
+ section, & abbrev_number, NULL, NULL);
+ if (entry == NULL)
+ {
+ if (form != DW_FORM_GNU_ref_alt)
+ warn (_("Offset %s used as value for DW_AT_import attribute of DIE at offset 0x%lx is too big.\n"),
+ dwarf_vmatoa ("x", uvalue),
+ (unsigned long) (orig_data - section->start));
+ }
else
{
- unsigned long abbrev_number;
- abbrev_entry * entry;
-
- abbrev_number = read_uleb128 (section->start + uvalue, NULL, end);
-
printf (_("\t[Abbrev Number: %ld"), abbrev_number);
- /* Don't look up abbrev for DW_FORM_ref_addr, as it very often will
- use different abbrev table, and we don't track .debug_info chunks
- yet. */
- if (form != DW_FORM_ref_addr)
- {
- for (entry = first_abbrev; entry != NULL; entry = entry->next)
- if (entry->entry == abbrev_number)
- break;
- if (entry != NULL)
- printf (" (%s)", get_TAG_name (entry->tag));
- }
+ printf (" (%s)", get_TAG_name (entry->tag));
printf ("]");
}
}
load_debug_section_with_follow (str_index_dwo, file);
load_debug_section_with_follow (debug_addr, file);
}
-
+
load_debug_section_with_follow (abbrev_sec, file);
if (debug_displays [abbrev_sec].section.start == NULL)
{
if (!do_loc && dwarf_start_die == 0)
introduce (section, FALSE);
+
+ free_all_abbrevs ();
+ free (cu_abbrev_map);
+ cu_abbrev_map = NULL;
+ next_free_abbrev_map_entry = 0;
- for (section_begin = start, unit = 0; start < end; unit++)
+ /* In order to be able to resolve DW_FORM_ref_attr forms we need
+ to load *all* of the abbrevs for all CUs in this .debug_info
+ section. This does effectively mean that we (partially) read
+ every CU header twice. */
+ for (section_begin = start; start < end;)
+ {
+ DWARF2_Internal_CompUnit compunit;
+ unsigned char * hdrptr;
+ dwarf_vma abbrev_base;
+ size_t abbrev_size;
+ dwarf_vma cu_offset;
+ unsigned int offset_size;
+ unsigned int initial_length_size;
+ struct cu_tu_set * this_set;
+ abbrev_list * list;
+
+ hdrptr = start;
+
+ SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 4, end);
+
+ if (compunit.cu_length == 0xffffffff)
+ {
+ SAFE_BYTE_GET_AND_INC (compunit.cu_length, hdrptr, 8, end);
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
+ }
+
+ SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end);
+
+ cu_offset = start - section_begin;
+
+ this_set = find_cu_tu_set_v2 (cu_offset, do_types);
+
+ if (compunit.cu_version < 5)
+ {
+ compunit.cu_unit_type = DW_UT_compile;
+ /* Initialize it due to a false compiler warning. */
+ compunit.cu_pointer_size = -1;
+ }
+ else
+ {
+ SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end);
+ do_types = (compunit.cu_unit_type == DW_UT_type);
+
+ SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end);
+ }
+
+ SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end);
+
+ if (this_set == NULL)
+ {
+ abbrev_base = 0;
+ abbrev_size = debug_displays [abbrev_sec].section.size;
+ }
+ else
+ {
+ abbrev_base = this_set->section_offsets [DW_SECT_ABBREV];
+ abbrev_size = this_set->section_sizes [DW_SECT_ABBREV];
+ }
+
+ list = find_abbrev_list_by_abbrev_offset (abbrev_base,
+ compunit.cu_abbrev_offset);
+ if (list == NULL)
+ {
+ unsigned char * next;
+
+ list = new_abbrev_list (abbrev_base,
+ compunit.cu_abbrev_offset);
+ next = process_abbrev_set
+ (((unsigned char *) debug_displays [abbrev_sec].section.start
+ + abbrev_base + compunit.cu_abbrev_offset),
+ ((unsigned char *) debug_displays [abbrev_sec].section.start
+ + abbrev_base + abbrev_size),
+ list);
+ list->start_of_next_abbrevs = next;
+ }
+
+ start = section_begin + cu_offset + compunit.cu_length
+ + initial_length_size;
+ record_abbrev_list_for_cu (cu_offset, start - section_begin, list);
+ }
+
+ for (start = section_begin, unit = 0; start < end; unit++)
{
DWARF2_Internal_CompUnit compunit;
unsigned char *hdrptr;
struct cu_tu_set *this_set;
dwarf_vma abbrev_base;
size_t abbrev_size;
+ abbrev_list * list = NULL;
hdrptr = start;
if ((do_loc || do_debug_loc || do_debug_ranges)
&& num_debug_info_entries == 0
+ && alloc_num_debug_info_entries > unit
&& ! do_types)
{
debug_information [unit].cu_offset = cu_offset;
dwarf_vmatoa ("x", compunit.cu_length),
offset_size == 8 ? "64-bit" : "32-bit");
printf (_(" Version: %d\n"), compunit.cu_version);
+ if (compunit.cu_version >= 5)
+ printf (_(" Unit Type: %s (%x)\n"),
+ get_DW_UT_name (compunit.cu_unit_type) ?: "???",
+ compunit.cu_unit_type);
printf (_(" Abbrev Offset: 0x%s\n"),
dwarf_vmatoa ("x", compunit.cu_abbrev_offset));
printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size);
}
if (compunit.cu_unit_type != DW_UT_compile
+ && compunit.cu_unit_type != DW_UT_partial
&& compunit.cu_unit_type != DW_UT_type)
{
warn (_("CU at offset %s contains corrupt or "
continue;
}
- free_abbrevs ();
-
/* Process the abbrevs used by this compilation unit. */
if (compunit.cu_abbrev_offset >= abbrev_size)
warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than abbrev section size (%lx)\n"),
(unsigned long) abbrev_base + abbrev_size,
(unsigned long) debug_displays [abbrev_sec].section.size);
else
- process_abbrev_section
- (((unsigned char *) debug_displays [abbrev_sec].section.start
- + abbrev_base + compunit.cu_abbrev_offset),
- ((unsigned char *) debug_displays [abbrev_sec].section.start
- + abbrev_base + abbrev_size));
+ {
+ list = find_abbrev_list_by_abbrev_offset (abbrev_base,
+ compunit.cu_abbrev_offset);
+ if (list == NULL)
+ {
+ unsigned char * next;
+
+ list = new_abbrev_list (abbrev_base,
+ compunit.cu_abbrev_offset);
+ next = process_abbrev_set
+ (((unsigned char *) debug_displays [abbrev_sec].section.start
+ + abbrev_base + compunit.cu_abbrev_offset),
+ ((unsigned char *) debug_displays [abbrev_sec].section.start
+ + abbrev_base + abbrev_size),
+ list);
+ list->start_of_next_abbrevs = next;
+ }
+ }
level = 0;
last_level = level;
saved_level = -1;
while (tags < start)
{
- unsigned int bytes_read;
unsigned long abbrev_number;
unsigned long die_offset;
abbrev_entry *entry;
die_offset = tags - section_begin;
- abbrev_number = read_uleb128 (tags, & bytes_read, start);
- tags += bytes_read;
+ READ_ULEB (abbrev_number, tags, start);
/* A null DIE marks the end of a list of siblings or it may also be
a section padding. */
/* Scan through the abbreviation list until we reach the
correct entry. */
- for (entry = first_abbrev;
- entry && entry->entry != abbrev_number;
- entry = entry->next)
+ if (list == NULL)
continue;
+ for (entry = list->first_abbrev; entry != NULL; entry = entry->next)
+ if (entry->number == abbrev_number)
+ break;
+
if (entry == NULL)
{
if (!do_loc && do_printing)
{
unsigned char *hdrptr;
unsigned int initial_length_size;
- unsigned char address_size, segment_selector_size;
/* Extract information from the Line Number Program Header.
(section 6.2.4 in the Dwarf3 doc). */
if (linfo->li_version >= 5)
{
- SAFE_BYTE_GET_AND_INC (address_size, hdrptr, 1, end);
+ SAFE_BYTE_GET_AND_INC (linfo->li_address_size, hdrptr, 1, end);
- SAFE_BYTE_GET_AND_INC (segment_selector_size, hdrptr, 1, end);
- if (segment_selector_size != 0)
+ SAFE_BYTE_GET_AND_INC (linfo->li_segment_size, hdrptr, 1, end);
+ if (linfo->li_segment_size != 0)
{
warn (_("The %s section contains "
"unsupported segment selector size: %d.\n"),
- section->name, segment_selector_size);
- return 0;
+ section->name, linfo->li_segment_size);
+ return NULL;
}
}
{
unsigned char *format_start, format_count, *format, formati;
dwarf_vma data_count, datai;
- unsigned int bytes_read, namepass, last_entry = 0;
-
+ unsigned int namepass, last_entry = 0;
+ const char * table_name = is_dir ? N_("Directory Table") : N_("File Name Table");
+
SAFE_BYTE_GET_AND_INC (format_count, data, 1, end);
+ if (do_checks && format_count > 5)
+ warn (_("Unexpectedly large number of columns in the %s (%u)\n"),
+ table_name, format_count);
+
format_start = data;
for (formati = 0; formati < format_count; formati++)
{
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ SKIP_ULEB (data, end);
+ SKIP_ULEB (data, end);
if (data == end)
{
- if (is_dir)
- warn (_("Corrupt directory format table entry\n"));
- else
- warn (_("Corrupt file name format table entry\n"));
+ warn (_("%s: Corrupt format description entry\n"), table_name);
return data;
}
}
- data_count = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- if (data == end)
+ READ_ULEB (data_count, data, end);
+ if (data_count == 0)
{
- if (is_dir)
- warn (_("Corrupt directory list\n"));
- else
- warn (_("Corrupt file name list\n"));
+ printf (_("\n The %s is empty.\n"), table_name);
return data;
}
-
- if (data_count == 0)
+ else if (data == end)
{
- if (is_dir)
- printf (_("\n The Directory Table is empty.\n"));
- else
- printf (_("\n The File Name Table is empty.\n"));
+ warn (_("%s: Corrupt entry count - expected %s but none found\n"),
+ table_name, dwarf_vmatoa ("x", data_count));
return data;
}
- if (is_dir)
- printf (_("\n The Directory Table (offset 0x%lx):\n"),
- (long) (data - start));
- else
- printf (_("\n The File Name Table (offset 0x%lx):\n"),
- (long) (data - start));
+ else if (format_count == 0)
+ {
+ warn (_("%s: format count is zero, but the table is not empty\n"),
+ table_name);
+ return end;
+ }
+
+ printf (_("\n The %s (offset 0x%lx, lines %s, columns %u):\n"),
+ table_name, (long) (data - start), dwarf_vmatoa ("u", data_count),
+ format_count);
printf (_(" Entry"));
/* Delay displaying name as the last entry for better screen layout. */
{
dwarf_vma content_type;
- content_type = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
+ READ_ULEB (content_type, format, end);
if ((content_type == DW_LNCT_path) == (namepass == 1))
switch (content_type)
{
printf (_("\tSize"));
break;
case DW_LNCT_MD5:
- printf (_("\tMD5"));
+ printf (_("\tMD5\t\t\t"));
break;
default:
printf (_("\t(Unknown format content type %s)"),
dwarf_vmatoa ("u", content_type));
}
- read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
+ SKIP_ULEB (format, end);
}
}
putchar ('\n');
{
dwarf_vma content_type, form;
- content_type = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
- form = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
- data = read_and_display_attr_value (0, form, 0, start, data, end, 0, 0,
- linfo->li_offset_size,
+ READ_ULEB (content_type, format, end);
+ READ_ULEB (form, format, end);
+ data = read_and_display_attr_value (0, form, 0, start, data, end,
+ 0, 0, linfo->li_offset_size,
linfo->li_version, NULL,
((content_type == DW_LNCT_path) != (namepass == 1)),
section, NULL, '\t', -1);
}
}
- if (data == end)
+
+ if (data == end && (datai < data_count - 1))
{
- if (is_dir)
- warn (_("Corrupt directory entries list\n"));
- else
- warn (_("Corrupt file name entries list\n"));
+ warn (_("\n%s: Corrupt entries list\n"), table_name);
return data;
}
putchar ('\n');
printf (_(" Offset: 0x%lx\n"), (long)(data - start));
printf (_(" Length: %ld\n"), (long) linfo.li_length);
printf (_(" DWARF Version: %d\n"), linfo.li_version);
+ if (linfo.li_version >= 5)
+ {
+ printf (_(" Address size (bytes): %d\n"), linfo.li_address_size);
+ printf (_(" Segment selector (bytes): %d\n"), linfo.li_segment_size);
+ }
printf (_(" Prologue Length: %d\n"), (int) linfo.li_prologue_length);
printf (_(" Minimum Instruction Length: %d\n"), linfo.li_min_insn_length);
if (linfo.li_version >= 4)
while (data < end && *data != 0)
{
unsigned char *name;
- unsigned int bytes_read;
+ dwarf_vma val;
printf (" %d\t", ++state_machine_regs.last_file_entry);
name = data;
data += strnlen ((char *) data, end - data) + 1;
- printf ("%s\t",
- dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
- printf ("%s\t",
- dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
- printf ("%s\t",
- dwarf_vmatoa ("u", read_uleb128 (data, & bytes_read, end)));
- data += bytes_read;
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
+ READ_ULEB (val, data, end);
+ printf ("%s\t", dwarf_vmatoa ("u", val));
printf ("%.*s\n", (int)(end - name), name);
if (data == end)
unsigned char op_code;
dwarf_signed_vma adv;
dwarf_vma uladv;
- unsigned int bytes_read;
printf (" [0x%08lx]", (long)(data - start));
putchar ('\n');
state_machine_regs.view++;
}
- else switch (op_code)
- {
- case DW_LNS_extended_op:
- data += process_extended_line_op (data, linfo.li_default_is_stmt, end);
- break;
-
- case DW_LNS_copy:
- printf (_(" Copy"));
- if (verbose_view || state_machine_regs.view)
- printf (_(" (view %u)\n"), state_machine_regs.view);
- else
- putchar ('\n');
- state_machine_regs.view++;
- break;
-
- case DW_LNS_advance_pc:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- if (linfo.li_max_ops_per_insn == 1)
- {
- uladv *= linfo.li_min_insn_length;
- state_machine_regs.address += uladv;
- if (uladv)
- state_machine_regs.view = 0;
- printf (_(" Advance PC by %s to 0x%s%s\n"),
- dwarf_vmatoa ("u", uladv),
- dwarf_vmatoa ("x", state_machine_regs.address),
- verbose_view && uladv
- ? _(" (reset view)") : "");
- }
- else
- {
- unsigned addrdelta
- = ((state_machine_regs.op_index + uladv)
- / linfo.li_max_ops_per_insn)
- * linfo.li_min_insn_length;
- state_machine_regs.address
- += addrdelta;
- state_machine_regs.op_index
- = (state_machine_regs.op_index + uladv)
- % linfo.li_max_ops_per_insn;
- if (addrdelta)
- state_machine_regs.view = 0;
- printf (_(" Advance PC by %s to 0x%s[%d]%s\n"),
- dwarf_vmatoa ("u", uladv),
- dwarf_vmatoa ("x", state_machine_regs.address),
- state_machine_regs.op_index,
- verbose_view && addrdelta
- ? _(" (reset view)") : "");
- }
- break;
-
- case DW_LNS_advance_line:
- adv = read_sleb128 (data, & bytes_read, end);
- data += bytes_read;
- state_machine_regs.line += adv;
- printf (_(" Advance Line by %s to %d\n"),
- dwarf_vmatoa ("d", adv),
- state_machine_regs.line);
- break;
-
- case DW_LNS_set_file:
- adv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- printf (_(" Set File Name to entry %s in the File Name Table\n"),
- dwarf_vmatoa ("d", adv));
- state_machine_regs.file = adv;
- break;
-
- case DW_LNS_set_column:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- printf (_(" Set column to %s\n"),
- dwarf_vmatoa ("u", uladv));
- state_machine_regs.column = uladv;
- break;
-
- case DW_LNS_negate_stmt:
- adv = state_machine_regs.is_stmt;
- adv = ! adv;
- printf (_(" Set is_stmt to %s\n"), dwarf_vmatoa ("d", adv));
- state_machine_regs.is_stmt = adv;
- break;
-
- case DW_LNS_set_basic_block:
- printf (_(" Set basic block\n"));
- state_machine_regs.basic_block = 1;
- break;
-
- case DW_LNS_const_add_pc:
- uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range);
- if (linfo.li_max_ops_per_insn)
- {
- uladv *= linfo.li_min_insn_length;
- state_machine_regs.address += uladv;
- if (uladv)
- state_machine_regs.view = 0;
- printf (_(" Advance PC by constant %s to 0x%s%s\n"),
- dwarf_vmatoa ("u", uladv),
- dwarf_vmatoa ("x", state_machine_regs.address),
- verbose_view && uladv
- ? _(" (reset view)") : "");
- }
- else
- {
- unsigned addrdelta
- = ((state_machine_regs.op_index + uladv)
- / linfo.li_max_ops_per_insn)
- * linfo.li_min_insn_length;
- state_machine_regs.address
- += addrdelta;
- state_machine_regs.op_index
- = (state_machine_regs.op_index + uladv)
- % linfo.li_max_ops_per_insn;
- if (addrdelta)
- state_machine_regs.view = 0;
- printf (_(" Advance PC by constant %s to 0x%s[%d]%s\n"),
- dwarf_vmatoa ("u", uladv),
- dwarf_vmatoa ("x", state_machine_regs.address),
- state_machine_regs.op_index,
- verbose_view && addrdelta
- ? _(" (reset view)") : "");
- }
- break;
-
- case DW_LNS_fixed_advance_pc:
- SAFE_BYTE_GET_AND_INC (uladv, data, 2, end);
- state_machine_regs.address += uladv;
- state_machine_regs.op_index = 0;
- printf (_(" Advance PC by fixed size amount %s to 0x%s\n"),
- dwarf_vmatoa ("u", uladv),
- dwarf_vmatoa ("x", state_machine_regs.address));
- /* Do NOT reset view. */
- break;
-
- case DW_LNS_set_prologue_end:
- printf (_(" Set prologue_end to true\n"));
- break;
-
- case DW_LNS_set_epilogue_begin:
- printf (_(" Set epilogue_begin to true\n"));
- break;
-
- case DW_LNS_set_isa:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- printf (_(" Set ISA to %s\n"), dwarf_vmatoa ("u", uladv));
- break;
-
- default:
- printf (_(" Unknown opcode %d with operands: "), op_code);
-
- if (standard_opcodes != NULL)
- for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
- {
- printf ("0x%s%s", dwarf_vmatoa ("x", read_uleb128 (data,
- &bytes_read, end)),
- i == 1 ? "" : ", ");
- data += bytes_read;
- }
- putchar ('\n');
- break;
- }
+ else
+ switch (op_code)
+ {
+ case DW_LNS_extended_op:
+ data += process_extended_line_op (data,
+ linfo.li_default_is_stmt,
+ end);
+ break;
+
+ case DW_LNS_copy:
+ printf (_(" Copy"));
+ if (verbose_view || state_machine_regs.view)
+ printf (_(" (view %u)\n"), state_machine_regs.view);
+ else
+ putchar ('\n');
+ state_machine_regs.view++;
+ break;
+
+ case DW_LNS_advance_pc:
+ READ_ULEB (uladv, data, end);
+ if (linfo.li_max_ops_per_insn == 1)
+ {
+ uladv *= linfo.li_min_insn_length;
+ state_machine_regs.address += uladv;
+ if (uladv)
+ state_machine_regs.view = 0;
+ printf (_(" Advance PC by %s to 0x%s%s\n"),
+ dwarf_vmatoa ("u", uladv),
+ dwarf_vmatoa ("x", state_machine_regs.address),
+ verbose_view && uladv
+ ? _(" (reset view)") : "");
+ }
+ else
+ {
+ unsigned addrdelta
+ = ((state_machine_regs.op_index + uladv)
+ / linfo.li_max_ops_per_insn)
+ * linfo.li_min_insn_length;
+ state_machine_regs.address
+ += addrdelta;
+ state_machine_regs.op_index
+ = (state_machine_regs.op_index + uladv)
+ % linfo.li_max_ops_per_insn;
+ if (addrdelta)
+ state_machine_regs.view = 0;
+ printf (_(" Advance PC by %s to 0x%s[%d]%s\n"),
+ dwarf_vmatoa ("u", uladv),
+ dwarf_vmatoa ("x", state_machine_regs.address),
+ state_machine_regs.op_index,
+ verbose_view && addrdelta
+ ? _(" (reset view)") : "");
+ }
+ break;
+
+ case DW_LNS_advance_line:
+ READ_SLEB (adv, data, end);
+ state_machine_regs.line += adv;
+ printf (_(" Advance Line by %s to %d\n"),
+ dwarf_vmatoa ("d", adv),
+ state_machine_regs.line);
+ break;
+
+ case DW_LNS_set_file:
+ READ_ULEB (uladv, data, end);
+ printf (_(" Set File Name to entry %s in the File Name Table\n"),
+ dwarf_vmatoa ("u", uladv));
+ state_machine_regs.file = uladv;
+ break;
+
+ case DW_LNS_set_column:
+ READ_ULEB (uladv, data, end);
+ printf (_(" Set column to %s\n"),
+ dwarf_vmatoa ("u", uladv));
+ state_machine_regs.column = uladv;
+ break;
+
+ case DW_LNS_negate_stmt:
+ adv = state_machine_regs.is_stmt;
+ adv = ! adv;
+ printf (_(" Set is_stmt to %s\n"), dwarf_vmatoa ("d", adv));
+ state_machine_regs.is_stmt = adv;
+ break;
+
+ case DW_LNS_set_basic_block:
+ printf (_(" Set basic block\n"));
+ state_machine_regs.basic_block = 1;
+ break;
+
+ case DW_LNS_const_add_pc:
+ uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range);
+ if (linfo.li_max_ops_per_insn)
+ {
+ uladv *= linfo.li_min_insn_length;
+ state_machine_regs.address += uladv;
+ if (uladv)
+ state_machine_regs.view = 0;
+ printf (_(" Advance PC by constant %s to 0x%s%s\n"),
+ dwarf_vmatoa ("u", uladv),
+ dwarf_vmatoa ("x", state_machine_regs.address),
+ verbose_view && uladv
+ ? _(" (reset view)") : "");
+ }
+ else
+ {
+ unsigned addrdelta
+ = ((state_machine_regs.op_index + uladv)
+ / linfo.li_max_ops_per_insn)
+ * linfo.li_min_insn_length;
+ state_machine_regs.address
+ += addrdelta;
+ state_machine_regs.op_index
+ = (state_machine_regs.op_index + uladv)
+ % linfo.li_max_ops_per_insn;
+ if (addrdelta)
+ state_machine_regs.view = 0;
+ printf (_(" Advance PC by constant %s to 0x%s[%d]%s\n"),
+ dwarf_vmatoa ("u", uladv),
+ dwarf_vmatoa ("x", state_machine_regs.address),
+ state_machine_regs.op_index,
+ verbose_view && addrdelta
+ ? _(" (reset view)") : "");
+ }
+ break;
+
+ case DW_LNS_fixed_advance_pc:
+ SAFE_BYTE_GET_AND_INC (uladv, data, 2, end);
+ state_machine_regs.address += uladv;
+ state_machine_regs.op_index = 0;
+ printf (_(" Advance PC by fixed size amount %s to 0x%s\n"),
+ dwarf_vmatoa ("u", uladv),
+ dwarf_vmatoa ("x", state_machine_regs.address));
+ /* Do NOT reset view. */
+ break;
+
+ case DW_LNS_set_prologue_end:
+ printf (_(" Set prologue_end to true\n"));
+ break;
+
+ case DW_LNS_set_epilogue_begin:
+ printf (_(" Set epilogue_begin to true\n"));
+ break;
+
+ case DW_LNS_set_isa:
+ READ_ULEB (uladv, data, end);
+ printf (_(" Set ISA to %s\n"), dwarf_vmatoa ("u", uladv));
+ break;
+
+ default:
+ printf (_(" Unknown opcode %d with operands: "), op_code);
+
+ if (standard_opcodes != NULL)
+ for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
+ {
+ READ_ULEB (uladv, data, end);
+ printf ("0x%s%s", dwarf_vmatoa ("x", uladv),
+ i == 1 ? "" : ", ");
+ }
+ putchar ('\n');
+ break;
+ }
}
putchar ('\n');
}
{
unsigned char *format_start, format_count, *format;
dwarf_vma formati, entryi;
- unsigned int bytes_read;
load_debug_section_with_follow (line_str, fileptr);
/* Skip directories format. */
SAFE_BYTE_GET_AND_INC (format_count, data, 1, end);
+ if (do_checks && format_count > 1)
+ warn (_("Unexpectedly large number of columns in the directory name table (%u)\n"),
+ format_count);
format_start = data;
for (formati = 0; formati < format_count; formati++)
{
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ SKIP_ULEB (data, end);
+ SKIP_ULEB (data, end);
}
- n_directories = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ READ_ULEB (n_directories, data, end);
if (data == end)
{
warn (_("Corrupt directories list\n"));
break;
}
- directory_table = (unsigned char **)
- xmalloc (n_directories * sizeof (unsigned char *));
+ if (n_directories == 0)
+ directory_table = NULL;
+ else
+ directory_table = (unsigned char **)
+ xmalloc (n_directories * sizeof (unsigned char *));
for (entryi = 0; entryi < n_directories; entryi++)
{
dwarf_vma content_type, form;
dwarf_vma uvalue;
- content_type = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
- form = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
+ READ_ULEB (content_type, format, end);
+ READ_ULEB (form, format, end);
if (data == end)
{
warn (_("Corrupt directories list\n"));
}
break;
}
- data = read_and_display_attr_value (0, form, 0, start, data, end,
- 0, 0,
+ data = read_and_display_attr_value (0, form, 0, start,
+ data, end, 0, 0,
linfo.li_offset_size,
linfo.li_version,
NULL, 1, section,
/* Skip files format. */
SAFE_BYTE_GET_AND_INC (format_count, data, 1, end);
+ 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++)
{
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
+ SKIP_ULEB (data, end);
+ SKIP_ULEB (data, end);
}
- n_files = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- if (data == end)
+ READ_ULEB (n_files, data, end);
+ if (data == end && n_files > 0)
{
warn (_("Corrupt file name list\n"));
break;
}
- file_table = (File_Entry *) xcalloc (1, n_files
- * sizeof (File_Entry));
+ if (n_files == 0)
+ file_table = NULL;
+ else
+ file_table = (File_Entry *) xcalloc (1, n_files
+ * sizeof (File_Entry));
for (entryi = 0; entryi < n_files; entryi++)
{
{
dwarf_vma content_type, form;
dwarf_vma uvalue;
+ unsigned char *tmp;
- content_type = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
- form = read_uleb128 (format, & bytes_read, end);
- format += bytes_read;
+ READ_ULEB (content_type, format, end);
+ READ_ULEB (form, format, end);
if (data == end)
{
warn (_("Corrupt file name list\n"));
end);
break;
case DW_FORM_udata:
- file->directory_index = read_uleb128 (data, NULL,
- end);
+ tmp = data;
+ READ_ULEB (file->directory_index, tmp, end);
break;
}
break;
}
- data = read_and_display_attr_value (0, form, 0, start, data, end,
- 0, 0,
+ data = read_and_display_attr_value (0, form, 0, start,
+ data, end, 0, 0,
linfo.li_offset_size,
linfo.li_version,
NULL, 1, section,
while (data < end && *data != 0)
{
- unsigned int bytes_read;
-
- /* Skip Name, directory index, last modification time and length
- of file. */
+ /* Skip Name, directory index, last modification
+ time and length of file. */
data += strnlen ((char *) data, end - data) + 1;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
-
+ SKIP_ULEB (data, end);
+ SKIP_ULEB (data, end);
+ SKIP_ULEB (data, end);
n_files++;
}
i = 0;
while (*ptr_file_name_table != 0)
{
- unsigned int bytes_read;
-
file_table[i].name = ptr_file_name_table;
ptr_file_name_table += strnlen ((char *) ptr_file_name_table,
end - ptr_file_name_table) + 1;
/* We are not interested in directory, time or size. */
- file_table[i].directory_index = read_uleb128 (ptr_file_name_table,
- & bytes_read, end);
- ptr_file_name_table += bytes_read;
- file_table[i].modification_date = read_uleb128 (ptr_file_name_table,
- & bytes_read, end);
- ptr_file_name_table += bytes_read;
- file_table[i].length = read_uleb128 (ptr_file_name_table, & bytes_read, end);
- ptr_file_name_table += bytes_read;
+ READ_ULEB (file_table[i].directory_index,
+ ptr_file_name_table, end);
+ READ_ULEB (file_table[i].modification_date,
+ ptr_file_name_table, end);
+ READ_ULEB (file_table[i].length,
+ ptr_file_name_table, end);
i++;
}
i = 0;
/* Print the Compilation Unit's name and a header. */
if (file_table == NULL)
- ;
+ printf (_("CU: No directory table\n"));
else if (directory_table == NULL)
printf (_("CU: %s:\n"), file_table[0].name);
else
printf ("%s:\n", file_table[0].name);
}
- printf (_("File name Line number Starting address View Stmt\n"));
+ if (n_files > 0)
+ printf (_("File name Line number Starting address View Stmt\n"));
+ else
+ printf (_("CU: Empty file name table\n"));
saved_linfo = linfo;
}
int xop;
int adv;
unsigned long int uladv;
- unsigned int bytes_read;
int is_special_opcode = 0;
op_code = *data++;
is_special_opcode = 1;
/* Increment view after printing this row. */
}
- else switch (op_code)
- {
- case DW_LNS_extended_op:
- {
- unsigned int ext_op_code_len;
- unsigned char ext_op_code;
- unsigned char *op_code_data = data;
-
- ext_op_code_len = read_uleb128 (op_code_data, &bytes_read,
- end_of_sequence);
- op_code_data += bytes_read;
-
- if (ext_op_code_len == 0)
- {
- warn (_("Badly formed extended line op encountered!\n"));
- break;
- }
- ext_op_code_len += bytes_read;
- ext_op_code = *op_code_data++;
- xop = ext_op_code;
- xop = -xop;
-
- switch (ext_op_code)
- {
- case DW_LNE_end_sequence:
- /* Reset stuff after printing this row. */
- break;
- case DW_LNE_set_address:
- SAFE_BYTE_GET_AND_INC (state_machine_regs.address,
- op_code_data,
- ext_op_code_len - bytes_read - 1,
- end);
- state_machine_regs.op_index = 0;
- state_machine_regs.view = 0;
- break;
- case DW_LNE_define_file:
- {
- file_table = (File_Entry *) xrealloc
- (file_table, (n_files + 1) * sizeof (File_Entry));
-
- ++state_machine_regs.last_file_entry;
- /* Source file name. */
- file_table[n_files].name = op_code_data;
- op_code_data += strlen ((char *) op_code_data) + 1;
- /* Directory index. */
- file_table[n_files].directory_index =
- read_uleb128 (op_code_data, & bytes_read,
- end_of_sequence);
- op_code_data += bytes_read;
- /* Last modification time. */
- file_table[n_files].modification_date =
- read_uleb128 (op_code_data, & bytes_read,
- end_of_sequence);
- op_code_data += bytes_read;
- /* File length. */
- file_table[n_files].length =
- read_uleb128 (op_code_data, & bytes_read,
- end_of_sequence);
-
- n_files++;
- break;
- }
- case DW_LNE_set_discriminator:
- case DW_LNE_HP_set_sequence:
- /* Simply ignored. */
- break;
-
- default:
- printf (_("UNKNOWN (%u): length %d\n"),
- ext_op_code, ext_op_code_len - bytes_read);
- break;
- }
- data += ext_op_code_len;
- break;
- }
- case DW_LNS_copy:
- /* Increment view after printing this row. */
- break;
-
- case DW_LNS_advance_pc:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- if (linfo.li_max_ops_per_insn == 1)
- {
- uladv *= linfo.li_min_insn_length;
- state_machine_regs.address += uladv;
- if (uladv)
- state_machine_regs.view = 0;
- }
- else
- {
- unsigned addrdelta
- = ((state_machine_regs.op_index + uladv)
- / linfo.li_max_ops_per_insn)
- * linfo.li_min_insn_length;
- state_machine_regs.address
- += addrdelta;
- state_machine_regs.op_index
- = (state_machine_regs.op_index + uladv)
- % linfo.li_max_ops_per_insn;
- if (addrdelta)
- state_machine_regs.view = 0;
- }
- break;
-
- case DW_LNS_advance_line:
- adv = read_sleb128 (data, & bytes_read, end);
- data += bytes_read;
- state_machine_regs.line += adv;
- break;
-
- case DW_LNS_set_file:
- adv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- state_machine_regs.file = adv;
-
- {
- unsigned file = state_machine_regs.file - 1;
- unsigned dir;
-
- 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 + 1, 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 %s\n"),
- dir, dwarf_vmatoa ("u", 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);
- }
- break;
-
- case DW_LNS_set_column:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- state_machine_regs.column = uladv;
- break;
-
- case DW_LNS_negate_stmt:
- adv = state_machine_regs.is_stmt;
- adv = ! adv;
- state_machine_regs.is_stmt = adv;
- break;
-
- case DW_LNS_set_basic_block:
- state_machine_regs.basic_block = 1;
- break;
-
- case DW_LNS_const_add_pc:
- uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range);
- if (linfo.li_max_ops_per_insn == 1)
- {
- uladv *= linfo.li_min_insn_length;
- state_machine_regs.address += uladv;
- if (uladv)
- state_machine_regs.view = 0;
- }
- else
- {
- unsigned addrdelta
- = ((state_machine_regs.op_index + uladv)
- / linfo.li_max_ops_per_insn)
- * linfo.li_min_insn_length;
- state_machine_regs.address
- += addrdelta;
- state_machine_regs.op_index
- = (state_machine_regs.op_index + uladv)
- % linfo.li_max_ops_per_insn;
- if (addrdelta)
- state_machine_regs.view = 0;
- }
- break;
-
- case DW_LNS_fixed_advance_pc:
- SAFE_BYTE_GET_AND_INC (uladv, data, 2, end);
- state_machine_regs.address += uladv;
- state_machine_regs.op_index = 0;
- /* Do NOT reset view. */
- break;
-
- case DW_LNS_set_prologue_end:
- break;
-
- case DW_LNS_set_epilogue_begin:
- break;
-
- case DW_LNS_set_isa:
- uladv = read_uleb128 (data, & bytes_read, end);
- data += bytes_read;
- printf (_(" Set ISA to %lu\n"), uladv);
- break;
-
- default:
- printf (_(" Unknown opcode %d with operands: "), op_code);
-
- if (standard_opcodes != NULL)
- for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
- {
- printf ("0x%s%s", dwarf_vmatoa ("x", read_uleb128 (data,
- &bytes_read, end)),
- i == 1 ? "" : ", ");
- data += bytes_read;
- }
- putchar ('\n');
- break;
- }
+ else
+ switch (op_code)
+ {
+ case DW_LNS_extended_op:
+ {
+ unsigned int ext_op_code_len;
+ unsigned char ext_op_code;
+ unsigned char *op_code_end;
+ unsigned char *op_code_data = data;
+
+ READ_ULEB (ext_op_code_len, op_code_data, end_of_sequence);
+ op_code_end = op_code_data + ext_op_code_len;
+ if (ext_op_code_len == 0 || op_code_end > end_of_sequence)
+ {
+ warn (_("Badly formed extended line op encountered!\n"));
+ break;
+ }
+ ext_op_code = *op_code_data++;
+ xop = ext_op_code;
+ xop = -xop;
+
+ switch (ext_op_code)
+ {
+ case DW_LNE_end_sequence:
+ /* Reset stuff after printing this row. */
+ break;
+ case DW_LNE_set_address:
+ SAFE_BYTE_GET_AND_INC (state_machine_regs.address,
+ op_code_data,
+ op_code_end - op_code_data,
+ op_code_end);
+ state_machine_regs.op_index = 0;
+ state_machine_regs.view = 0;
+ break;
+ case DW_LNE_define_file:
+ file_table = (File_Entry *) xrealloc
+ (file_table, (n_files + 1) * sizeof (File_Entry));
+
+ ++state_machine_regs.last_file_entry;
+ /* Source file name. */
+ file_table[n_files].name = op_code_data;
+ op_code_data += strlen ((char *) op_code_data) + 1;
+ /* Directory index. */
+ READ_ULEB (file_table[n_files].directory_index,
+ op_code_data, op_code_end);
+ /* Last modification time. */
+ READ_ULEB (file_table[n_files].modification_date,
+ op_code_data, op_code_end);
+ /* File length. */
+ READ_ULEB (file_table[n_files].length,
+ op_code_data, op_code_end);
+ n_files++;
+ break;
+
+ case DW_LNE_set_discriminator:
+ case DW_LNE_HP_set_sequence:
+ /* Simply ignored. */
+ break;
+
+ default:
+ printf (_("UNKNOWN (%u): length %ld\n"),
+ ext_op_code, (long int) (op_code_data - data));
+ break;
+ }
+ data = op_code_end;
+ break;
+ }
+ case DW_LNS_copy:
+ /* Increment view after printing this row. */
+ break;
+
+ case DW_LNS_advance_pc:
+ READ_ULEB (uladv, data, end);
+ if (linfo.li_max_ops_per_insn == 1)
+ {
+ uladv *= linfo.li_min_insn_length;
+ state_machine_regs.address += uladv;
+ if (uladv)
+ state_machine_regs.view = 0;
+ }
+ else
+ {
+ unsigned addrdelta
+ = ((state_machine_regs.op_index + uladv)
+ / linfo.li_max_ops_per_insn)
+ * linfo.li_min_insn_length;
+ state_machine_regs.address
+ += addrdelta;
+ state_machine_regs.op_index
+ = (state_machine_regs.op_index + uladv)
+ % linfo.li_max_ops_per_insn;
+ if (addrdelta)
+ state_machine_regs.view = 0;
+ }
+ break;
+
+ case DW_LNS_advance_line:
+ READ_SLEB (adv, data, end);
+ state_machine_regs.line += adv;
+ break;
+
+ case DW_LNS_set_file:
+ READ_ULEB (uladv, data, end);
+ state_machine_regs.file = uladv;
+
+ {
+ unsigned file = state_machine_regs.file - 1;
+ unsigned dir;
+
+ 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 + 1, 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 %s\n"),
+ dir, dwarf_vmatoa ("u", 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);
+ }
+ break;
+
+ case DW_LNS_set_column:
+ READ_ULEB (uladv, data, end);
+ state_machine_regs.column = uladv;
+ break;
+
+ case DW_LNS_negate_stmt:
+ adv = state_machine_regs.is_stmt;
+ adv = ! adv;
+ state_machine_regs.is_stmt = adv;
+ break;
+
+ case DW_LNS_set_basic_block:
+ state_machine_regs.basic_block = 1;
+ break;
+
+ case DW_LNS_const_add_pc:
+ uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range);
+ if (linfo.li_max_ops_per_insn == 1)
+ {
+ uladv *= linfo.li_min_insn_length;
+ state_machine_regs.address += uladv;
+ if (uladv)
+ state_machine_regs.view = 0;
+ }
+ else
+ {
+ unsigned addrdelta
+ = ((state_machine_regs.op_index + uladv)
+ / linfo.li_max_ops_per_insn)
+ * linfo.li_min_insn_length;
+ state_machine_regs.address
+ += addrdelta;
+ state_machine_regs.op_index
+ = (state_machine_regs.op_index + uladv)
+ % linfo.li_max_ops_per_insn;
+ if (addrdelta)
+ state_machine_regs.view = 0;
+ }
+ break;
+
+ case DW_LNS_fixed_advance_pc:
+ SAFE_BYTE_GET_AND_INC (uladv, data, 2, end);
+ state_machine_regs.address += uladv;
+ state_machine_regs.op_index = 0;
+ /* Do NOT reset view. */
+ break;
+
+ case DW_LNS_set_prologue_end:
+ break;
+
+ case DW_LNS_set_epilogue_begin:
+ break;
+
+ case DW_LNS_set_isa:
+ READ_ULEB (uladv, data, end);
+ printf (_(" Set ISA to %lu\n"), uladv);
+ break;
+
+ default:
+ printf (_(" Unknown opcode %d with operands: "), op_code);
+
+ if (standard_opcodes != NULL)
+ for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
+ {
+ dwarf_vma val;
+
+ READ_ULEB (val, data, end);
+ printf ("0x%s%s", dwarf_vmatoa ("x", val),
+ i == 1 ? "" : ", ");
+ }
+ putchar ('\n');
+ break;
+ }
/* Only Special opcodes, DW_LNS_copy and DW_LNE_end_sequence adds a row
to the DWARF address/line matrix. */
strncpy (newFileName,
fileName + fileNameLength - MAX_FILENAME_LENGTH,
MAX_FILENAME_LENGTH + 1);
+ /* FIXME: This is to pacify gcc-10 which can warn that the
+ strncpy above might leave a non-NUL terminated string
+ in newFileName. It won't, but gcc's analysis doesn't
+ quite go far enough to discover this. */
+ newFileName[MAX_FILENAME_LENGTH] = 0;
}
else
{
strncpy (newFileName, fileName, fileNameLength + 1);
}
+ /* A row with end_seq set to true has a meaningful address, but
+ the other information in the same row is not significant.
+ In such a row, print line as "-", and don't print
+ view/is_stmt. */
if (!do_wide || (fileNameLength <= MAX_FILENAME_LENGTH))
{
if (linfo.li_max_ops_per_insn == 1)
- printf ("%-35s %11d %#18" DWARF_VMA_FMT "x",
- newFileName, state_machine_regs.line,
- state_machine_regs.address);
+ {
+ if (xop == -DW_LNE_end_sequence)
+ printf ("%-35s %11s %#18" DWARF_VMA_FMT "x",
+ newFileName, "-",
+ state_machine_regs.address);
+ else
+ printf ("%-35s %11d %#18" DWARF_VMA_FMT "x",
+ newFileName, state_machine_regs.line,
+ state_machine_regs.address);
+ }
else
- printf ("%-35s %11d %#18" DWARF_VMA_FMT "x[%d]",
- newFileName, state_machine_regs.line,
- state_machine_regs.address,
- state_machine_regs.op_index);
+ {
+ if (xop == -DW_LNE_end_sequence)
+ printf ("%-35s %11s %#18" DWARF_VMA_FMT "x[%d]",
+ newFileName, "-",
+ state_machine_regs.address,
+ state_machine_regs.op_index);
+ else
+ printf ("%-35s %11d %#18" DWARF_VMA_FMT "x[%d]",
+ newFileName, state_machine_regs.line,
+ state_machine_regs.address,
+ state_machine_regs.op_index);
+ }
}
else
{
if (linfo.li_max_ops_per_insn == 1)
- printf ("%s %11d %#18" DWARF_VMA_FMT "x",
- newFileName, state_machine_regs.line,
- state_machine_regs.address);
+ {
+ if (xop == -DW_LNE_end_sequence)
+ printf ("%s %11s %#18" DWARF_VMA_FMT "x",
+ newFileName, "-",
+ state_machine_regs.address);
+ else
+ printf ("%s %11d %#18" DWARF_VMA_FMT "x",
+ newFileName, state_machine_regs.line,
+ state_machine_regs.address);
+ }
else
- printf ("%s %11d %#18" DWARF_VMA_FMT "x[%d]",
- newFileName, state_machine_regs.line,
- state_machine_regs.address,
- state_machine_regs.op_index);
+ {
+ if (xop == -DW_LNE_end_sequence)
+ printf ("%s %11s %#18" DWARF_VMA_FMT "x[%d]",
+ newFileName, "-",
+ state_machine_regs.address,
+ state_machine_regs.op_index);
+ else
+ printf ("%s %11d %#18" DWARF_VMA_FMT "x[%d]",
+ newFileName, state_machine_regs.line,
+ state_machine_regs.address,
+ state_machine_regs.op_index);
+ }
}
- if (state_machine_regs.view)
- printf (" %6u", state_machine_regs.view);
- else
- printf (" ");
+ if (xop != -DW_LNE_end_sequence)
+ {
+ if (state_machine_regs.view)
+ printf (" %6u", state_machine_regs.view);
+ else
+ printf (" ");
- if (state_machine_regs.is_stmt)
- printf (" x");
+ if (state_machine_regs.is_stmt)
+ printf (" x");
+ }
putchar ('\n');
state_machine_regs.view++;
unsigned char *start = section->start;
unsigned char *end = start + section->size;
unsigned char *curr = start;
- unsigned int bytes_read;
enum dwarf_macinfo_record_type op;
introduce (section, FALSE);
{
unsigned int filenum;
- lineno = read_uleb128 (curr, & bytes_read, end);
- curr += bytes_read;
- filenum = read_uleb128 (curr, & bytes_read, end);
- curr += bytes_read;
-
+ READ_ULEB (lineno, curr, end);
+ READ_ULEB (filenum, curr, end);
printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"),
lineno, filenum);
}
break;
case DW_MACINFO_define:
- lineno = read_uleb128 (curr, & bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
string = curr;
curr += strnlen ((char *) string, end - string) + 1;
printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"),
break;
case DW_MACINFO_undef:
- lineno = read_uleb128 (curr, & bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
string = curr;
curr += strnlen ((char *) string, end - string) + 1;
printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"),
{
unsigned int constant;
- constant = read_uleb128 (curr, & bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (constant, curr, end);
string = curr;
curr += strnlen ((char *) string, end - string) + 1;
printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"),
struct dwarf_section *section = &debug_displays [line].section;
unsigned char *hdrptr, *dirtable, *file_name;
unsigned int offset_size, initial_length_size;
- unsigned int version, opcode_base, bytes_read;
+ unsigned int version, opcode_base;
dwarf_vma length, diridx;
const unsigned char * end;
for (; hdrptr < end && *hdrptr != '\0' && fileidx > 1; fileidx--)
{
hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
- read_uleb128 (hdrptr, &bytes_read, end);
- hdrptr += bytes_read;
- read_uleb128 (hdrptr, &bytes_read, end);
- hdrptr += bytes_read;
- read_uleb128 (hdrptr, &bytes_read, end);
- hdrptr += bytes_read;
+ SKIP_ULEB (hdrptr, end);
+ SKIP_ULEB (hdrptr, end);
+ SKIP_ULEB (hdrptr, end);
}
if (hdrptr >= end || *hdrptr == '\0')
return NULL;
hdrptr += strnlen ((char *) hdrptr, end - hdrptr) + 1;
if (hdrptr >= end)
return NULL;
- diridx = read_uleb128 (hdrptr, &bytes_read, end);
+ READ_ULEB (diridx, hdrptr, end);
if (diridx == 0)
return file_name;
for (; dirtable < end && *dirtable != '\0' && diridx > 1; diridx--)
unsigned char *end = start + section->size;
unsigned char *curr = start;
unsigned char *extended_op_buf[256];
- unsigned int bytes_read;
load_debug_section_with_follow (str, file);
load_debug_section_with_follow (line, file);
+ load_debug_section_with_follow (str_index, file);
introduce (section, FALSE);
{
SAFE_BYTE_GET_AND_INC (op, curr, 1, end);
extended_ops[op] = curr;
- nargs = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (nargs, curr, end);
if (nargs == 0)
printf (_(" DW_MACRO_%02x has no arguments\n"), op);
else
switch (op)
{
+ case DW_MACRO_define:
+ READ_ULEB (lineno, curr, end);
+ string = curr;
+ curr += strnlen ((char *) string, end - string) + 1;
+ printf (_(" DW_MACRO_define - lineno : %d macro : %s\n"),
+ lineno, string);
+ break;
+
+ case DW_MACRO_undef:
+ READ_ULEB (lineno, curr, end);
+ string = curr;
+ curr += strnlen ((char *) string, end - string) + 1;
+ printf (_(" DW_MACRO_undef - lineno : %d macro : %s\n"),
+ lineno, string);
+ break;
+
case DW_MACRO_start_file:
{
unsigned int filenum;
unsigned char *file_name = NULL, *dir_name = NULL;
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
- filenum = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
+ READ_ULEB (filenum, curr, end);
if ((flags & 2) == 0)
error (_("DW_MACRO_start_file used, but no .debug_line offset provided.\n"));
printf (_(" DW_MACRO_end_file\n"));
break;
- case DW_MACRO_define:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
- string = curr;
- curr += strnlen ((char *) string, end - string) + 1;
- printf (_(" DW_MACRO_define - lineno : %d macro : %s\n"),
- lineno, string);
- break;
-
- case DW_MACRO_undef:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
- string = curr;
- curr += strnlen ((char *) string, end - string) + 1;
- printf (_(" DW_MACRO_undef - lineno : %d macro : %s\n"),
- lineno, string);
- break;
-
case DW_MACRO_define_strp:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
string = fetch_indirect_string (offset);
printf (_(" DW_MACRO_define_strp - lineno : %d macro : %s\n"),
break;
case DW_MACRO_undef_strp:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ READ_ULEB (lineno, curr, end);
SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
string = fetch_indirect_string (offset);
printf (_(" DW_MACRO_undef_strp - lineno : %d macro : %s\n"),
break;
case DW_MACRO_define_sup:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ 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%lx\n"),
lineno, (unsigned long) offset);
break;
case DW_MACRO_undef_sup:
- lineno = read_uleb128 (curr, &bytes_read, end);
- curr += bytes_read;
+ 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%lx\n"),
lineno, (unsigned long) offset);
(unsigned long) offset);
break;
+ case DW_MACRO_define_strx:
+ case DW_MACRO_undef_strx:
+ READ_ULEB (lineno, curr, end);
+ READ_ULEB (offset, curr, end);
+ string = (const unsigned char *)
+ fetch_indexed_string (offset, NULL, offset_size, FALSE);
+ if (op == DW_MACRO_define_strx)
+ printf (" DW_MACRO_define_strx ");
+ else
+ printf (" DW_MACRO_undef_strx ");
+ if (do_wide)
+ printf (_("(with offset %s) "), dwarf_vmatoa ("x", offset));
+ printf (_("lineno : %d macro : %s\n"),
+ lineno, string);
+ break;
+
default:
+ if (op >= DW_MACRO_lo_user && op <= DW_MACRO_hi_user)
+ {
+ printf (_(" <Target Specific macro op: %#x - UNHANDLED"), op);
+ break;
+ }
+
if (extended_ops == NULL || extended_ops[op] == NULL)
{
error (_(" Unknown macro opcode %02x seen\n"), op);
/* Skip over unhandled opcodes. */
dwarf_vma nargs, n;
unsigned char *desc = extended_ops[op];
- nargs = read_uleb128 (desc, &bytes_read, end);
- desc += bytes_read;
+ READ_ULEB (nargs, desc, end);
if (nargs == 0)
{
printf (_(" DW_MACRO_%02x\n"), op);
{
abbrev_entry *entry;
unsigned char *start = section->start;
- unsigned char *end = start + section->size;
+ const unsigned char *end = start + section->size;
introduce (section, FALSE);
do
{
- unsigned char *last;
-
- free_abbrevs ();
+ abbrev_list * list;
+ dwarf_vma offset;
- last = start;
- start = process_abbrev_section (start, end);
+ offset = start - section->start;
+ list = find_abbrev_list_by_abbrev_offset (0, offset);
+ if (list == NULL)
+ {
+ list = new_abbrev_list (0, offset);
+ start = process_abbrev_set (start, end, list);
+ list->start_of_next_abbrevs = start;
+ }
+ else
+ start = list->start_of_next_abbrevs;
- if (first_abbrev == NULL)
+ if (list->first_abbrev == NULL)
continue;
- printf (_(" Number TAG (0x%lx)\n"), (long) (last - section->start));
+ printf (_(" Number TAG (0x%lx)\n"), (long) offset);
- for (entry = first_abbrev; entry; entry = entry->next)
+ for (entry = list->first_abbrev; entry; entry = entry->next)
{
abbrev_attr *attr;
printf (" %ld %s [%s]\n",
- entry->entry,
+ entry->number,
get_TAG_name (entry->tag),
entry->children ? _("has children") : _("no children"));
dwarf_vma off = vstart - section->start;
dwarf_vma vbegin, vend;
- unsigned int bytes_read;
- vbegin = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (vbegin, vstart, section_end);
if (vstart == section_end)
- {
- vstart -= bytes_read;
- break;
- }
-
- vend = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ break;
+ READ_ULEB (vend, vstart, section_end);
printf (" %8.8lx ", (unsigned long) off);
print_dwarf_view (vbegin, pointer_size, 1);
if (vstart)
{
- unsigned int bytes_read;
-
off = offset + (vstart - *start_ptr);
- vbegin = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (vbegin, vstart, section_end);
print_dwarf_view (vbegin, pointer_size, 1);
- vend = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (vend, vstart, section_end);
print_dwarf_view (vend, pointer_size, 1);
printf (_("views at %8.8lx for:\n %*s "),
unsigned int pointer_size;
unsigned int offset_size;
int dwarf_version;
- unsigned int bytes_read;
/* Initialize it due to a false compiler warning. */
dwarf_vma begin = -1, vbegin = -1;
SAFE_BYTE_GET_AND_INC (llet, start, 1, section_end);
- if (vstart && llet == DW_LLE_offset_pair)
+ if (vstart && (llet == DW_LLE_offset_pair
+ || llet == DW_LLE_start_end
+ || llet == DW_LLE_start_length))
{
off = offset + (vstart - *start_ptr);
- vbegin = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (vbegin, vstart, section_end);
print_dwarf_view (vbegin, pointer_size, 1);
- vend = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (vend, vstart, section_end);
print_dwarf_view (vend, pointer_size, 1);
printf (_("views at %8.8lx for:\n %*s "),
printf (_("<End of list>\n"));
break;
case DW_LLE_offset_pair:
- begin = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
- end = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (begin, start, section_end);
+ begin += base_address;
+ READ_ULEB (end, start, section_end);
+ end += base_address;
+ break;
+ case DW_LLE_start_end:
+ SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, section_end);
+ SAFE_BYTE_GET_AND_INC (end, start, pointer_size, section_end);
+ break;
+ case DW_LLE_start_length:
+ SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, section_end);
+ READ_ULEB (end, start, section_end);
+ end += begin;
break;
case DW_LLE_base_address:
SAFE_BYTE_GET_AND_INC (base_address, start, pointer_size,
case DW_LLE_view_pair:
if (vstart)
printf (_("View pair entry in loclist with locviews attribute\n"));
- vbegin = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (vbegin, start, section_end);
print_dwarf_view (vbegin, pointer_size, 1);
- vend = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (vend, start, section_end);
print_dwarf_view (vend, pointer_size, 1);
printf (_("views for:\n"));
}
if (llet == DW_LLE_end_of_list)
break;
- if (llet != DW_LLE_offset_pair)
+ if (llet != DW_LLE_offset_pair
+ && llet != DW_LLE_start_end
+ && llet != DW_LLE_start_length)
continue;
if (start + 2 > section_end)
break;
}
- length = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (length, start, section_end);
- print_dwarf_vma (begin + base_address, pointer_size);
- print_dwarf_vma (end + base_address, pointer_size);
+ print_dwarf_vma (begin, pointer_size);
+ print_dwarf_vma (end, pointer_size);
putchar ('(');
need_frame_base = decode_location_expression (start,
unsigned short length;
int need_frame_base;
unsigned int idx;
- unsigned int bytes_read;
if (debug_info_entry >= num_debug_info_entries)
{
dwarf_vma view;
dwarf_vma off = offset + (vstart - *start_ptr);
- view = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (view, vstart, section_end);
print_dwarf_view (view, 8, 1);
- view = read_uleb128 (vstart, &bytes_read, section_end);
- vstart += bytes_read;
+ READ_ULEB (view, vstart, section_end);
print_dwarf_view (view, 8, 1);
printf (_("views at %8.8lx for:\n %*s "),
printf (_("<End of list>\n"));
return;
case 1: /* A base-address entry. */
- idx = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (idx, start, section_end);
print_addr_index (idx, 8);
printf ("%*s", 9 + (vstart ? 2 * 6 : 0), "");
printf (_("(base address selection entry)\n"));
continue;
case 2: /* A start/end entry. */
- idx = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (idx, start, section_end);
print_addr_index (idx, 8);
- idx = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (idx, start, section_end);
print_addr_index (idx, 8);
break;
case 3: /* A start/length entry. */
- idx = read_uleb128 (start, &bytes_read, section_end);
- start += bytes_read;
+ READ_ULEB (idx, start, section_end);
print_addr_index (idx, 8);
SAFE_BYTE_GET_AND_INC (idx, start, 4, section_end);
printf ("%08x ", idx);
display_debug_str_offsets (struct dwarf_section *section,
void *file ATTRIBUTE_UNUSED)
{
+ unsigned long idx;
+
if (section->size == 0)
{
printf (_("\nThe %s section is empty.\n"), section->name);
return 0;
}
- /* TODO: Dump the contents. This is made somewhat difficult by not knowing
- what the offset size is for this section. */
+
+ unsigned char *start = section->start;
+ unsigned char *end = start + section->size;
+ unsigned char *curr = start;
+
+ const char * suffix = strrchr (section->name, '.');
+ bfd_boolean dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? TRUE : FALSE;
+
+ if (dwo)
+ load_debug_section_with_follow (str_dwo, file);
+ else
+ load_debug_section_with_follow (str, file);
+
+ introduce (section, FALSE);
+
+ while (curr < end)
+ {
+ dwarf_vma length;
+ dwarf_vma entry_length;
+
+ SAFE_BYTE_GET_AND_INC (length, curr, 4, end);
+ /* FIXME: We assume that this means 64-bit DWARF is being used. */
+ if (length == 0xffffffff)
+ {
+ SAFE_BYTE_GET (length, curr, 8, end);
+ entry_length = 8;
+ }
+ else
+ entry_length = 4;
+
+ if (length == 0)
+ {
+ /* This is probably an old style .debug_str_offset section which
+ just contains offsets and no header (and the first offset is 0). */
+ length = section->size;
+ curr = section->start;
+
+ printf (_(" Length: %#lx\n"), (unsigned long) length);
+ printf (_(" Index Offset [String]\n"));
+ }
+ else
+ {
+ int version;
+ SAFE_BYTE_GET_AND_INC (version, curr, 2, end);
+ if (version != 5)
+ warn (_("Unexpected version number in str_offset header: %#x\n"), version);
+
+ int padding;
+ SAFE_BYTE_GET_AND_INC (padding, curr, 2, end);
+ if (padding != 0)
+ warn (_("Unexpected value in str_offset header's padding field: %#x\n"), padding);
+
+ printf (_(" Length: %#lx\n"), (unsigned long) length);
+ printf (_(" Version: %#lx\n"), (unsigned long) version);
+ printf (_(" Index Offset [String]\n"));
+ }
+
+ for (idx = 0; length >= entry_length && curr < end; idx++)
+ {
+ dwarf_vma offset;
+ const unsigned char * string;
+
+ SAFE_BYTE_GET_AND_INC (offset, curr, entry_length, end);
+ if (dwo)
+ string = (const unsigned char *)
+ fetch_indexed_string (idx, NULL, entry_length, dwo);
+ else
+ string = fetch_indirect_string (offset);
+
+ printf (" %8lu %8s %s\n", idx, dwarf_vmatoa ("x", offset),
+ string);
+ }
+ }
+
return 1;
}
enum dwarf_range_list_entry rlet;
/* Initialize it due to a false compiler warning. */
dwarf_vma begin = -1, length, end = -1;
- unsigned int bytes_read;
if (start + 1 > finish)
{
break;
case DW_RLE_start_length:
SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, finish);
- length = read_uleb128 (start, &bytes_read, finish);
- start += bytes_read;
+ READ_ULEB (length, start, finish);
end = begin + length;
break;
case DW_RLE_offset_pair:
- begin = read_uleb128 (start, &bytes_read, finish);
- start += bytes_read;
- end = read_uleb128 (start, &bytes_read, finish);
- start += bytes_read;
+ READ_ULEB (begin, start, finish);
+ READ_ULEB (end, start, finish);
break;
case DW_RLE_start_end:
SAFE_BYTE_GET_AND_INC (begin, start, pointer_size, finish);
int is_rnglists = strstr (section->name, "debug_rnglists") != NULL;
/* Initialize it due to a false compiler warning. */
unsigned char address_size = 0;
+ dwarf_vma last_offset = 0;
if (bytes == 0)
{
continue;
}
+ /* 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
+ the `range_entries' list, so we can easily ignore duplicates
+ here. */
+ if (i > 0 && last_offset == offset)
+ continue;
+ last_offset = offset;
+
if (dwarf_check != 0 && i > 0)
{
if (start < next)
}
Frame_Chunk;
+typedef const char *(*dwarf_regname_lookup_ftype) (unsigned int);
+static dwarf_regname_lookup_ftype dwarf_regnames_lookup_func;
static const char *const *dwarf_regnames;
static unsigned int dwarf_regnames_count;
+
/* A marker for a col_type that means this column was never referenced
in the frame info. */
#define DW_CFA_unreferenced (-1)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* 93 - 100 */
};
-void
+static void
init_dwarf_regnames_i386 (void)
{
dwarf_regnames = dwarf_regnames_i386;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_i386);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
-void
+static void
init_dwarf_regnames_iamcu (void)
{
dwarf_regnames = dwarf_regnames_iamcu;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_iamcu);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_x86_64[] =
"k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"
};
-void
+static void
init_dwarf_regnames_x86_64 (void)
{
dwarf_regnames = dwarf_regnames_x86_64;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_x86_64);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_aarch64[] =
"z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
};
-void
+static void
init_dwarf_regnames_aarch64 (void)
{
dwarf_regnames = dwarf_regnames_aarch64;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_aarch64);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_s390[] =
"v24", "v26", "v28", "v30", "v25", "v27", "v29", "v31",
};
-void
+static void
init_dwarf_regnames_s390 (void)
{
dwarf_regnames = dwarf_regnames_s390;
dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_s390);
+ dwarf_regnames_lookup_func = regname_internal_by_table_only;
}
static const char *const dwarf_regnames_riscv[] =
"ft8", "ft9", "ft10", "ft11" /* 60 - 63 */
};
-void
+/* A RISC-V replacement for REGNAME_INTERNAL_BY_TABLE_ONLY which handles
+ the large number of CSRs. */
+
+static const char *
+regname_internal_riscv (unsigned int regno)
+{
+ const char *name = NULL;
+
+ /* Lookup in the table first, this covers GPR and FPR. */
+ if (regno < ARRAY_SIZE (dwarf_regnames_riscv))
+ name = dwarf_regnames_riscv [regno];
+ else if (regno >= 4096 && regno <= 8191)
+ {
+ /* This might be a CSR, these live in a sparse number space from 4096
+ to 8191 These numbers are defined in the RISC-V ELF ABI
+ document. */
+ switch (regno)
+ {
+#define DECLARE_CSR(NAME,VALUE,CLASS,DEFINE_VER,ABORT_VER) \
+ case VALUE + 4096: name = #NAME; break;
+#include "opcode/riscv-opc.h"
+#undef DECLARE_CSR
+
+ default:
+ {
+ static char csr_name[10];
+ snprintf (csr_name, sizeof (csr_name), "csr%d", (regno - 4096));
+ name = csr_name;
+ }
+ break;
+ }
+ }
+
+ return name;
+}
+
+static void
init_dwarf_regnames_riscv (void)
{
- dwarf_regnames = dwarf_regnames_riscv;
- dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_riscv);
+ dwarf_regnames = NULL;
+ dwarf_regnames_count = 8192;
+ dwarf_regnames_lookup_func = regname_internal_riscv;
}
void
init_dwarf_regnames_by_elf_machine_code (unsigned int e_machine)
{
+ dwarf_regnames_lookup_func = NULL;
+
switch (e_machine)
{
case EM_386:
}
}
-static const char *
-regname (unsigned int regno, int row)
+/* Initialize the DWARF register name lookup state based on the
+ architecture and specific machine type of a BFD. */
+
+void
+init_dwarf_regnames_by_bfd_arch_and_mach (enum bfd_architecture arch,
+ unsigned long mach)
{
- static char reg[64];
+ dwarf_regnames_lookup_func = NULL;
+
+ switch (arch)
+ {
+ case bfd_arch_i386:
+ switch (mach)
+ {
+ case bfd_mach_x86_64:
+ case bfd_mach_x86_64_intel_syntax:
+ case bfd_mach_x64_32:
+ case bfd_mach_x64_32_intel_syntax:
+ init_dwarf_regnames_x86_64 ();
+ break;
+
+ default:
+ init_dwarf_regnames_i386 ();
+ break;
+ }
+ break;
+
+ case bfd_arch_iamcu:
+ init_dwarf_regnames_iamcu ();
+ break;
+
+ case bfd_arch_aarch64:
+ init_dwarf_regnames_aarch64();
+ break;
- if (dwarf_regnames
+ case bfd_arch_s390:
+ init_dwarf_regnames_s390 ();
+ break;
+
+ case bfd_arch_riscv:
+ init_dwarf_regnames_riscv ();
+ break;
+
+ default:
+ break;
+ }
+}
+
+static const char *
+regname_internal_by_table_only (unsigned int regno)
+{
+ if (dwarf_regnames != NULL
&& regno < dwarf_regnames_count
&& dwarf_regnames [regno] != NULL)
+ return dwarf_regnames [regno];
+
+ return NULL;
+}
+
+static const char *
+regname (unsigned int regno, int name_only_p)
+{
+ static char reg[64];
+
+ const char *name = NULL;
+
+ if (dwarf_regnames_lookup_func != NULL)
+ name = dwarf_regnames_lookup_func (regno);
+
+ if (name != NULL)
{
- if (row)
- return dwarf_regnames [regno];
- snprintf (reg, sizeof (reg), "r%d (%s)", regno,
- dwarf_regnames [regno]);
+ if (name_only_p)
+ return name;
+ snprintf (reg, sizeof (reg), "r%d (%s)", regno, name);
}
else
snprintf (reg, sizeof (reg), "r%d", regno);
{
int version;
Frame_Chunk *fc;
- unsigned int length_return;
unsigned char *augmentation_data = NULL;
bfd_size_type augmentation_data_len = 0;
fc->segment_size = 0;
}
- READ_ULEB (fc->code_factor);
- READ_SLEB (fc->data_factor);
+ READ_ULEB (fc->code_factor, start, end);
+ READ_SLEB (fc->data_factor, start, end);
if (version == 1)
{
}
else
{
- READ_ULEB (fc->ra);
+ READ_ULEB (fc->ra, start, end);
}
if (fc->augmentation[0] == 'z')
{
- READ_ULEB (augmentation_data_len);
+ READ_ULEB (augmentation_data_len, start, end);
augmentation_data = start;
/* PR 17512: file: 11042-2589-0.004. */
if (augmentation_data_len > (bfd_size_type) (end - start))
Frame_Chunk *remembered_state = NULL;
Frame_Chunk *rs;
bfd_boolean is_eh = strcmp (section->name, ".eh_frame") == 0;
- unsigned int length_return;
unsigned int max_regs = 0;
const char *bad_reg = _("bad register: ");
unsigned int saved_eh_addr_size = eh_addr_size;
unsigned int offset_size;
unsigned int initial_length_size;
bfd_boolean all_nops;
+ static Frame_Chunk fde_fc;
saved_start = start;
else
{
unsigned char *look_for;
- static Frame_Chunk fde_fc;
unsigned long segment_selector;
if (is_eh)
if (cie->augmentation[0] == 'z')
{
- READ_ULEB (augmentation_data_len);
+ READ_ULEB (augmentation_data_len, start, end);
augmentation_data = start;
/* PR 17512 file: 722-8446-0.004 and PR 22386. */
if (augmentation_data_len > (bfd_size_type) (end - start))
case DW_CFA_advance_loc:
break;
case DW_CFA_offset:
- SKIP_ULEB ();
+ SKIP_ULEB (start, end);
if (frame_need_space (fc, opa) >= 0)
fc->col_type[opa] = DW_CFA_undefined;
break;
break;
case DW_CFA_offset_extended:
case DW_CFA_val_offset:
- READ_ULEB (reg);
- SKIP_ULEB ();
+ READ_ULEB (reg, start, end);
+ SKIP_ULEB (start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_restore_extended:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_undefined:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_same_value:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_register:
- READ_ULEB (reg);
- SKIP_ULEB ();
+ READ_ULEB (reg, start, end);
+ SKIP_ULEB (start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_def_cfa:
- SKIP_ULEB ();
- SKIP_ULEB ();
+ SKIP_ULEB (start, end);
+ SKIP_ULEB (start, end);
break;
case DW_CFA_def_cfa_register:
- SKIP_ULEB ();
+ SKIP_ULEB (start, end);
break;
case DW_CFA_def_cfa_offset:
- SKIP_ULEB ();
+ SKIP_ULEB (start, end);
break;
case DW_CFA_def_cfa_expression:
- READ_ULEB (temp);
+ READ_ULEB (temp, start, end);
new_start = start + temp;
if (new_start < start)
{
break;
case DW_CFA_expression:
case DW_CFA_val_expression:
- READ_ULEB (reg);
- READ_ULEB (temp);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (temp, start, end);
new_start = start + temp;
if (new_start < start)
{
break;
case DW_CFA_offset_extended_sf:
case DW_CFA_val_offset_sf:
- READ_ULEB (reg);
- SKIP_SLEB ();
+ READ_ULEB (reg, start, end);
+ SKIP_SLEB (start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_def_cfa_sf:
- SKIP_ULEB ();
- SKIP_SLEB ();
+ SKIP_ULEB (start, end);
+ SKIP_SLEB (start, end);
break;
case DW_CFA_def_cfa_offset_sf:
- SKIP_SLEB ();
+ SKIP_SLEB (start, end);
break;
case DW_CFA_MIPS_advance_loc8:
start += 8;
break;
case DW_CFA_GNU_args_size:
- SKIP_ULEB ();
+ SKIP_ULEB (start, end);
break;
case DW_CFA_GNU_negative_offset_extended:
- READ_ULEB (reg);
- SKIP_ULEB ();
+ READ_ULEB (reg, start, end);
+ SKIP_ULEB (start, end);
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
break;
case DW_CFA_offset:
- READ_ULEB (roffs);
+ READ_ULEB (roffs, start, end);
if (opa >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_offset_extended:
- READ_ULEB (reg);
- READ_ULEB (roffs);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (roffs, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_val_offset:
- READ_ULEB (reg);
- READ_ULEB (roffs);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (roffs, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_restore_extended:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_undefined:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_same_value:
- READ_ULEB (reg);
+ READ_ULEB (reg, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_register:
- READ_ULEB (reg);
- READ_ULEB (roffs);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (roffs, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_def_cfa:
- READ_ULEB (fc->cfa_reg);
- READ_ULEB (fc->cfa_offset);
+ READ_ULEB (fc->cfa_reg, start, end);
+ READ_ULEB (fc->cfa_offset, start, end);
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa: %s ofs %d\n",
break;
case DW_CFA_def_cfa_register:
- READ_ULEB (fc->cfa_reg);
+ READ_ULEB (fc->cfa_reg, start, end);
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_register: %s\n",
break;
case DW_CFA_def_cfa_offset:
- READ_ULEB (fc->cfa_offset);
+ READ_ULEB (fc->cfa_offset, start, end);
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_offset: %d\n", (int) fc->cfa_offset);
break;
break;
case DW_CFA_def_cfa_expression:
- READ_ULEB (ul);
+ READ_ULEB (ul, start, end);
if (start >= block_end || ul > (unsigned long) (block_end - start))
{
printf (_(" DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
break;
case DW_CFA_expression:
- READ_ULEB (reg);
- READ_ULEB (ul);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (ul, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
/* PR 17512: file: 069-133014-0.006. */
break;
case DW_CFA_val_expression:
- READ_ULEB (reg);
- READ_ULEB (ul);
+ READ_ULEB (reg, start, end);
+ READ_ULEB (ul, start, end);
if (reg >= (unsigned int) fc->ncols)
reg_prefix = bad_reg;
tmp = start + ul;
break;
case DW_CFA_offset_extended_sf:
- READ_ULEB (reg);
- READ_SLEB (l);
+ READ_ULEB (reg, start, end);
+ READ_SLEB (l, start, end);
if (frame_need_space (fc, reg) < 0)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_val_offset_sf:
- READ_ULEB (reg);
- READ_SLEB (l);
+ READ_ULEB (reg, start, end);
+ READ_SLEB (l, start, end);
if (frame_need_space (fc, reg) < 0)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
break;
case DW_CFA_def_cfa_sf:
- READ_ULEB (fc->cfa_reg);
- READ_ULEB (fc->cfa_offset);
+ READ_ULEB (fc->cfa_reg, start, end);
+ READ_ULEB (fc->cfa_offset, start, end);
fc->cfa_offset = fc->cfa_offset * fc->data_factor;
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
break;
case DW_CFA_def_cfa_offset_sf:
- READ_ULEB (fc->cfa_offset);
+ READ_ULEB (fc->cfa_offset, start, end);
fc->cfa_offset *= fc->data_factor;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_offset_sf: %d\n", (int) fc->cfa_offset);
break;
case DW_CFA_GNU_args_size:
- READ_ULEB (ul);
+ READ_ULEB (ul, start, end);
if (! do_debug_frames_interp)
printf (" DW_CFA_GNU_args_size: %ld\n", ul);
break;
case DW_CFA_GNU_negative_offset_extended:
- READ_ULEB (reg);
- READ_SLEB (l);
+ READ_ULEB (reg, start, end);
+ READ_SLEB (l, start, end);
l = - l;
if (frame_need_space (fc, reg) < 0)
reg_prefix = bad_reg;
if (do_debug_frames_interp && ! all_nops)
frame_display_row (fc, &need_col_headers, &max_regs);
+ if (fde_fc.col_type != NULL)
+ {
+ free (fde_fc.col_type);
+ fde_fc.col_type = NULL;
+ }
+ if (fde_fc.col_offset != NULL)
+ {
+ free (fde_fc.col_offset);
+ fde_fc.col_offset = NULL;
+ }
+
start = block_end;
eh_addr_size = saved_eh_addr_size;
}
unsigned char *abbrevptr = abbrev_table;
for (;;)
{
- unsigned int bytes_read;
- const dwarf_vma abbrev_tag = read_uleb128 (abbrevptr, &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
+ dwarf_vma abbrev_tag;
+
+ READ_ULEB (abbrev_tag, abbrevptr, abbrev_table_end);
if (abbrev_tag == 0)
break;
if (abbrev_lookup_used == abbrev_lookup_allocated)
entry->abbrev_lookup_ptr = abbrevptr;
/* Skip DWARF tag. */
- read_uleb128 (abbrevptr, &bytes_read, abbrev_table_end);
- abbrevptr += bytes_read;
+ SKIP_ULEB (abbrevptr, abbrev_table_end);
for (;;)
{
- const dwarf_vma xindex = read_uleb128 (abbrevptr,
- &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
- const dwarf_vma form = read_uleb128 (abbrevptr, &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
+ dwarf_vma xindex, form;
+
+ READ_ULEB (xindex, abbrevptr, abbrev_table_end);
+ READ_ULEB (form, abbrevptr, abbrev_table_end);
if (xindex == 0 && form == 0)
break;
}
unsigned char *entryptr = entry_pool + entry_offset;
- // We need to scan first whether there is a single or multiple
- // entries. TAGNO is -2 for the first entry, it is -1 for the
- // initial tag read of the second entry, then it becomes 0 for the
- // first entry for real printing etc.
+ /* We need to scan first whether there is a single or multiple
+ entries. TAGNO is -2 for the first entry, it is -1 for the
+ initial tag read of the second entry, then it becomes 0 for the
+ first entry for real printing etc. */
int tagno = -2;
/* Initialize it due to a false compiler warning. */
dwarf_vma second_abbrev_tag = -1;
for (;;)
{
- unsigned int bytes_read;
- const dwarf_vma abbrev_tag = read_uleb128 (entryptr, &bytes_read,
- unit_end);
- entryptr += bytes_read;
+ dwarf_vma abbrev_tag;
+ dwarf_vma dwarf_tag;
+ const struct abbrev_lookup_entry *entry;
+
+ READ_ULEB (abbrev_tag, entryptr, unit_end);
if (tagno == -1)
{
second_abbrev_tag = abbrev_tag;
(tagno == 0 && second_abbrev_tag == 0 ? " " : "\n\t"),
(unsigned long) abbrev_tag);
- const struct abbrev_lookup_entry *entry;
for (entry = abbrev_lookup;
entry < abbrev_lookup + abbrev_lookup_used;
entry++)
break;
}
abbrevptr = entry->abbrev_lookup_ptr;
- const dwarf_vma dwarf_tag = read_uleb128 (abbrevptr, &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
+ READ_ULEB (dwarf_tag, abbrevptr, abbrev_table_end);
if (tagno >= 0)
printf (" %s", get_TAG_name (dwarf_tag));
for (;;)
{
- const dwarf_vma xindex = read_uleb128 (abbrevptr,
- &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
- const dwarf_vma form = read_uleb128 (abbrevptr, &bytes_read,
- abbrev_table_end);
- abbrevptr += bytes_read;
+ dwarf_vma xindex, form;
+
+ READ_ULEB (xindex, abbrevptr, abbrev_table_end);
+ READ_ULEB (form, abbrevptr, abbrev_table_end);
if (xindex == 0 && form == 0)
break;
if (id_len < 0x14)
return NULL;
- build_id_data = calloc (1, sizeof * build_id_data);
- if (build_id_data == NULL)
- return NULL;
-
+ build_id_data = (Build_id_data *) data;
build_id_data->len = id_len;
build_id_data->data = section->start + namelen;
- * (Build_id_data **) data = build_id_data;
-
return name;
}
first_separate_info = i;
}
+#if HAVE_LIBDEBUGINFOD
+/* Query debuginfod servers for the target debuglink or debugaltlink
+ file. If successful, store the path of the file in filename and
+ return TRUE, otherwise return FALSE. */
+
+static bfd_boolean
+debuginfod_fetch_separate_debug_info (struct dwarf_section * section,
+ char ** filename,
+ void * file)
+{
+ size_t build_id_len;
+ unsigned char * build_id;
+
+ if (strcmp (section->uncompressed_name, ".gnu_debuglink") == 0)
+ {
+ /* Get the build-id of file. */
+ build_id = get_build_id (file);
+ build_id_len = 0;
+ }
+ else if (strcmp (section->uncompressed_name, ".gnu_debugaltlink") == 0)
+ {
+ /* Get the build-id of the debugaltlink file. */
+ unsigned int filelen;
+
+ filelen = strnlen ((const char *)section->start, section->size);
+ if (filelen == section->size)
+ /* Corrupt debugaltlink. */
+ return FALSE;
+
+ build_id = section->start + filelen + 1;
+ build_id_len = section->size - (filelen + 1);
+
+ if (build_id_len == 0)
+ return FALSE;
+ }
+ else
+ return FALSE;
+
+ if (build_id)
+ {
+ int fd;
+ debuginfod_client * client;
+
+ client = debuginfod_begin ();
+ if (client == NULL)
+ return FALSE;
+
+ /* Query debuginfod servers for the target file. If found its path
+ will be stored in filename. */
+ fd = debuginfod_find_debuginfo (client, build_id, build_id_len, filename);
+ debuginfod_end (client);
+
+ /* Only free build_id if we allocated space for a hex string
+ in get_build_id (). */
+ if (build_id_len == 0)
+ free (build_id);
+
+ if (fd >= 0)
+ {
+ /* File successfully retrieved. Close fd since we want to
+ use open_debug_file () on filename instead. */
+ close (fd);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+#endif
+
static void *
load_separate_debug_info (const char * main_filename,
struct dwarf_section * xlink,
parse_func_type parse_func,
check_func_type check_func,
- void * func_data)
+ void * func_data,
+ void * file ATTRIBUTE_UNUSED)
{
const char * separate_filename;
char * debug_filename;
{
warn (_("Corrupt debuglink section: %s\n"),
xlink->name ? xlink->name : xlink->uncompressed_name);
- return FALSE;
+ return NULL;
}
/* Attempt to locate the separate file.
if (check_func (debug_filename, func_data))
goto found;
+#if HAVE_LIBDEBUGINFOD
+ {
+ char * tmp_filename;
+
+ if (debuginfod_fetch_separate_debug_info (xlink,
+ & tmp_filename,
+ file))
+ {
+ /* File successfully downloaded from server, replace
+ debug_filename with the file's path. */
+ free (debug_filename);
+ debug_filename = tmp_filename;
+ goto found;
+ }
+ }
+#endif
+
/* Failed to find the file. */
warn (_("could not find separate debug file '%s'\n"), separate_filename);
warn (_("tried: %s\n"), debug_filename);
sprintf (debug_filename, "%s", separate_filename);
warn (_("tried: %s\n"), debug_filename);
+#if HAVE_LIBDEBUGINFOD
+ {
+ char *urls = getenv (DEBUGINFOD_URLS_ENV_VAR);
+ if (urls == NULL)
+ urls = "";
+
+ warn (_("tried: DEBUGINFOD_URLS=%s\n"), urls);
+ }
+#endif
+
free (canon_dir);
free (debug_filename);
return NULL;
{
warn (_("failed to open separate debug file: %s\n"), debug_filename);
free (debug_filename);
- return FALSE;
+ return NULL;
}
/* FIXME: We do not check to see if there are any other separate debug info
return separate_handle;
}
+/* Load a debuglink section and/or a debugaltlink section, if either are present.
+ Recursively check the loaded files for more of these sections.
+ FIXME: Should also check for DWO_* entries in the newlu loaded files. */
+
+static void
+check_for_and_load_links (void * file, const char * filename)
+{
+ void * handle = NULL;
+
+ if (load_debug_section (gnu_debugaltlink, file))
+ {
+ Build_id_data build_id_data;
+
+ handle = load_separate_debug_info (filename,
+ & debug_displays[gnu_debugaltlink].section,
+ parse_gnu_debugaltlink,
+ check_gnu_debugaltlink,
+ & build_id_data,
+ file);
+ if (handle)
+ {
+ assert (handle == first_separate_info->handle);
+ check_for_and_load_links (first_separate_info->handle,
+ first_separate_info->filename);
+ }
+ }
+
+ if (load_debug_section (gnu_debuglink, file))
+ {
+ unsigned long crc32;
+
+ handle = load_separate_debug_info (filename,
+ & debug_displays[gnu_debuglink].section,
+ parse_gnu_debuglink,
+ check_gnu_debuglink,
+ & crc32,
+ file);
+ if (handle)
+ {
+ assert (handle == first_separate_info->handle);
+ check_for_and_load_links (first_separate_info->handle,
+ first_separate_info->filename);
+ }
+ }
+}
+
/* Load the separate debug info file(s) attached to FILE, if any exist.
Returns TRUE if any were found, FALSE otherwise.
If TRUE is returned then the linked list starting at first_separate_info
return FALSE;
/* FIXME: We do not check for the presence of both link sections in the same file. */
- /* FIXME: We do not check the separate debug info file to see if it too contains debuglinks. */
/* FIXME: We do not check for the presence of multiple, same-name debuglink sections. */
/* FIXME: We do not check for the presence of a dwo link as well as a debuglink. */
- if (load_debug_section (gnu_debugaltlink, file))
- {
- Build_id_data * build_id_data;
-
- load_separate_debug_info (filename,
- & debug_displays[gnu_debugaltlink].section,
- parse_gnu_debugaltlink,
- check_gnu_debugaltlink,
- & build_id_data);
- }
-
- if (load_debug_section (gnu_debuglink, file))
- {
- unsigned long crc32;
-
- load_separate_debug_info (filename,
- & debug_displays[gnu_debuglink].section,
- parse_gnu_debuglink,
- check_gnu_debuglink,
- & crc32);
- }
-
+ check_for_and_load_links (file, filename);
if (first_separate_info != NULL)
return TRUE;
{
unsigned int i;
- free_abbrevs ();
+ free_all_abbrevs ();
+ free (cu_abbrev_map);
+ cu_abbrev_map = NULL;
+ next_free_abbrev_map_entry = 0;
+
for (i = 0; i < max; i++)
free_debug_section ((enum dwarf_section_display_enum) i);
if (debug_information != NULL)
{
- if (num_debug_info_entries != DEBUG_INFO_UNAVAILABLE)
+ for (i = 0; i < alloc_num_debug_info_entries; i++)
{
- for (i = 0; i < num_debug_info_entries; i++)
+ if (debug_information [i].max_loc_offsets)
{
- 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 [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 = NULL;
{ "ranges", & do_debug_aranges, 1 },
{ "rawline", & do_debug_lines, FLAG_DEBUG_LINES_RAW },
{ "str", & do_debug_str, 1 },
+ { "str-offsets", & do_debug_str_offsets, 1 },
/* These trace_* sections are used by Itanium VMS. */
{ "trace_abbrev", & do_trace_abbrevs, 1 },
{ "trace_aranges", & do_trace_aranges, 1 },
case 'l': do_debug_lines |= FLAG_DEBUG_LINES_RAW; break;
case 'L': do_debug_lines |= FLAG_DEBUG_LINES_DECODED; break;
case 'm': do_debug_macinfo = 1; break;
+ case 'O': do_debug_str_offsets = 1; break;
case 'o': do_debug_loc = 1; break;
case 'p': do_debug_pubnames = 1; break;
case 'R': do_debug_ranges = 1; break;
do_debug_cu_index = 1;
do_follow_links = 1;
do_debug_links = 1;
+ do_debug_str_offsets = 1;
}
#define NO_ABBREVS NULL, NULL, NULL, 0, 0, 0, NULL, 0, NULL
{ { ".debug_macro.dwo", ".zdebug_macro.dwo", NO_ABBREVS }, display_debug_macro, &do_debug_macinfo, TRUE },
{ { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo", NO_ABBREVS }, display_debug_macinfo, &do_debug_macinfo, FALSE },
{ { ".debug_str.dwo", ".zdebug_str.dwo", NO_ABBREVS }, display_debug_str, &do_debug_str, TRUE },
- { { ".debug_str_offsets", ".zdebug_str_offsets", NO_ABBREVS }, display_debug_str_offsets, NULL, FALSE },
- { { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo", NO_ABBREVS }, display_debug_str_offsets, NULL, FALSE },
+ { { ".debug_str_offsets", ".zdebug_str_offsets", NO_ABBREVS }, display_debug_str_offsets, &do_debug_str_offsets, TRUE },
+ { { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo", NO_ABBREVS }, display_debug_str_offsets, &do_debug_str_offsets, TRUE },
{ { ".debug_addr", ".zdebug_addr", NO_ABBREVS }, display_debug_addr, &do_debug_addr, TRUE },
{ { ".debug_cu_index", "", NO_ABBREVS }, display_cu_index, &do_debug_cu_index, FALSE },
{ { ".debug_tu_index", "", NO_ABBREVS }, display_cu_index, &do_debug_cu_index, FALSE },