/* dwarf.c -- display DWARF contents of a BFD binary file
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
+ Copyright (C) 2005-2021 Free Software Foundation, Inc.
This file is part of GNU Binutils.
#include "sysdep.h"
#include "libiberty.h"
#include "bfd.h"
-#include "bfd_stdint.h"
+#include <stdint.h>
#include "bucomm.h"
#include "elfcomm.h"
#include "elf/common.h"
#include "safe-ctype.h"
#include <assert.h>
+#ifdef HAVE_LIBDEBUGINFOD
+#include <elfutils/debuginfod.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
#undef MAX
#undef MIN
#define MAX(a, b) ((a) > (b) ? (a) : (b))
{
dwo_type type;
const char * value;
+ dwarf_vma cu_offset;
struct dwo_info * next;
} dwo_info;
-static dwo_info * first_dwo_info = NULL;
-static bfd_boolean need_dwo_info;
+static dwo_info *first_dwo_info = NULL;
+static bool need_dwo_info;
separate_info * first_separate_info = NULL;
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_debug_cu_index;
int do_wide;
int do_debug_links;
-int do_follow_links;
+int do_follow_links = DEFAULT_FOR_FOLLOW_LINKS;
+bool do_checks;
int dwarf_cutoff_level = -1;
unsigned long dwarf_start_die;
static struct cu_tu_set *cu_sets = NULL;
static struct cu_tu_set *tu_sets = NULL;
-static bfd_boolean load_cu_tu_indexes (void *);
+static bool load_cu_tu_indexes (void *);
/* An array that indicates for a given level of CU nesting whether
the latest DW_AT_type seen for that level was a signed type or
an unsigned type. */
#define MAX_CU_NESTING (1 << 8)
-static bfd_boolean level_type_signed[MAX_CU_NESTING];
+static bool level_type_signed[MAX_CU_NESTING];
/* Values for do_debug_lines. */
#define FLAG_DEBUG_LINES_RAW 1
/* 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
+ If STATUS_RETURN is 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,
const unsigned char *const end,
- bfd_boolean sign,
+ bool sign,
unsigned int *length_return,
int *status_return)
{
while (data < end)
{
unsigned char byte = *data++;
+ unsigned char lost, mask;
+
num_read++;
- if (shift < sizeof (result) * 8)
+ if (shift < CHAR_BIT * sizeof (result))
{
result |= ((dwarf_vma) (byte & 0x7f)) << shift;
- if ((result >> shift) != (byte & 0x7f))
- /* Overflow. */
- status |= 2;
+ /* These bits overflowed. */
+ lost = byte ^ (result >> shift);
+ /* And this is the mask of possible overflow bits. */
+ mask = 0x7f ^ ((dwarf_vma) 0x7f << shift >> shift);
shift += 7;
}
- else if ((byte & 0x7f) != 0)
+ else
+ {
+ lost = byte;
+ mask = 0x7f;
+ }
+ if ((lost & mask) != (sign && (dwarf_signed_vma) result < 0 ? mask : 0))
status |= 2;
if ((byte & 0x80) == 0)
{
status &= ~1;
- if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
+ if (sign && shift < CHAR_BIT * sizeof (result) && (byte & 0x40))
result |= -((dwarf_vma) 1 << shift);
break;
}
if (offset >= section->size)
{
- warn (_("DW_FORM_strp offset too big: %s\n"),
+ warn (_("DW_FORM_strp offset too big: 0x%s\n"),
dwarf_vmatoa ("x", offset));
return (const unsigned char *) _("<offset is too big>");
}
ret = (const unsigned char *)
_("<no NUL byte at end of .debug_str section>");
- return ret;
+ return ret;
}
static const unsigned char *
if (offset >= section->size)
{
- warn (_("DW_FORM_line_strp offset too big: %s\n"),
+ warn (_("DW_FORM_line_strp offset too big: 0x%s\n"),
dwarf_vmatoa ("x", offset));
return (const unsigned char *) _("<offset is too big>");
}
static const char *
fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
- dwarf_vma offset_size, bfd_boolean dwo)
+ dwarf_vma offset_size, bool dwo)
{
enum dwarf_section_display_enum str_sec_idx = dwo ? str_dwo : str;
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: 0x%s vs 0x%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)
{
- warn (_("DW_FORM_GNU_str_index indirect offset too big: %s\n"),
+ warn (_("DW_FORM_GNU_str_index indirect offset too big: 0x%s\n"),
dwarf_vmatoa ("x", str_offset));
return _("<indirect index offset is too big>");
}
if (offset + bytes > section->size)
{
- warn (_("Offset into section %s too big: %s\n"),
+ warn (_("Offset into section %s too big: 0x%s\n"),
section->name, dwarf_vmatoa ("x", offset));
return "<offset too big>";
}
/* 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
+record_abbrev_list_for_cu (dwarf_vma start, dwarf_vma end, abbrev_list * list)
+{
+ 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 ++;
+}
static void
-free_abbrevs (void)
+free_all_abbrevs (void)
{
- abbrev_entry *abbrv;
+ abbrev_list * list;
- for (abbrv = first_abbrev; abbrv;)
+ 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 long entry;
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)
children = *start++;
- add_abbrev (entry, tag, children);
+ add_abbrev (entry, tag, children, list);
do
{
break;
}
- add_abbrev_attr (attribute, form, implicit_const);
+ add_abbrev_attr (attribute, form, implicit_const, list);
}
while (attribute != 0);
}
return ret;
}
-
+
warn (_("DW_FORM_GNU_strp_alt offset (%s) too big or no string sections available\n"),
dwarf_vmatoa ("x", offset));
return _("<offset is too big>");
}
static void
-add_dwo_info (const char * field, dwo_type type)
+add_dwo_info (const char * value, dwarf_vma cu_offset, dwo_type type)
{
dwo_info * dwinfo = xmalloc (sizeof * dwinfo);
- dwinfo->type = type;
- dwinfo->value = field;
- dwinfo->next = first_dwo_info;
+ dwinfo->type = type;
+ dwinfo->value = value;
+ dwinfo->cu_offset = cu_offset;
+ dwinfo->next = first_dwo_info;
first_dwo_info = dwinfo;
}
static void
-add_dwo_name (const char * name)
+add_dwo_name (const char * name, dwarf_vma cu_offset)
{
- add_dwo_info (name, DWO_NAME);
+ add_dwo_info (name, cu_offset, DWO_NAME);
}
static void
-add_dwo_dir (const char * dir)
+add_dwo_dir (const char * dir, dwarf_vma cu_offset)
{
- add_dwo_info (dir, DWO_DIR);
+ add_dwo_info (dir, cu_offset, DWO_DIR);
}
static void
-add_dwo_id (const char * id)
+add_dwo_id (const char * id, dwarf_vma cu_offset)
{
- add_dwo_info (id, DWO_ID);
+ add_dwo_info (id, cu_offset, DWO_ID);
}
static void
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;
case DW_FORM_ref1:
case DW_FORM_flag:
case DW_FORM_data1:
+ case DW_FORM_strx1:
+ case DW_FORM_addrx1:
SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
break;
+ case DW_FORM_strx3:
+ case DW_FORM_addrx3:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 3, end);
+ break;
+
case DW_FORM_ref2:
case DW_FORM_data2:
+ case DW_FORM_strx2:
+ case DW_FORM_addrx2:
SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
break;
case DW_FORM_ref4:
case DW_FORM_data4:
+ case DW_FORM_strx4:
+ case DW_FORM_addrx4:
SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
break;
case DW_FORM_ref_udata:
case DW_FORM_udata:
case DW_FORM_GNU_str_index:
+ case DW_FORM_strx:
case DW_FORM_GNU_addr_index:
+ case DW_FORM_addrx:
READ_ULEB (uvalue, data, end);
break;
case DW_FORM_ref8:
+ {
+ dwarf_vma high_bits;
+
+ SAFE_BYTE_GET64 (data, &high_bits, &uvalue, end);
+ data += 8;
+ if (sizeof (uvalue) > 4)
+ uvalue += high_bits << 32;
+ else if (high_bits != 0)
+ {
+ /* FIXME: What to do ? */
+ return NULL;
+ }
+ break;
+ }
+
case DW_FORM_data8:
+ case DW_FORM_ref_sig8:
data += 8;
break;
case DW_FORM_block:
case DW_FORM_exprloc:
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 void
-get_type_signedness (unsigned char * start,
- unsigned char * data,
- unsigned const char * end,
- dwarf_vma pointer_size,
- dwarf_vma offset_size,
- int dwarf_version,
- bfd_boolean * is_signed,
- bfd_boolean is_nested)
+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;
- abbrev_attr * attr;
+ unsigned char * data;
- * is_signed = FALSE;
+ if (abbrev_num_return != NULL)
+ * abbrev_num_return = 0;
+ if (data_return != NULL)
+ * data_return = NULL;
- READ_ULEB (abbrev_number, data, end);
+ switch (form)
+ {
+ case DW_FORM_GNU_ref_alt:
+ case DW_FORM_ref_sig8:
+ /* 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_ref_sup4:
+ case DW_FORM_ref_sup8:
+ break;
- for (entry = first_abbrev;
- entry != NULL && entry->entry != abbrev_number;
- entry = entry->next)
- continue;
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
+ 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)
- /* FIXME: Issue a warning ? */
- return;
+ 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 (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,
+ bool *is_signed,
+ unsigned int nesting)
+{
+ abbrev_attr * attr;
+
+ * is_signed = false;
+
+#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:
case DW_ATE_unsigned:
case DW_ATE_unsigned_char:
case DW_ATE_unsigned_fixed:
- * is_signed = FALSE;
+ * is_signed = false;
break;
default:
case DW_ATE_imaginary_float:
case DW_ATE_decimal_float:
case DW_ATE_signed_fixed:
- * is_signed = TRUE;
+ * is_signed = true;
break;
}
break;
}
static void
-read_and_print_leb128 (unsigned char * data,
- unsigned int * bytes_read,
- unsigned const char * end,
- bfd_boolean is_signed)
+read_and_print_leb128 (unsigned char *data,
+ unsigned int *bytes_read,
+ unsigned const char *end,
+ bool is_signed)
{
int status;
dwarf_vma val = read_leb128 (data, end, is_signed, bytes_read, &status);
if (status != 0)
- report_leb_status (status);
+ report_leb_status (status, __FILE__, __LINE__);
else
printf ("%s", dwarf_vmatoa (is_signed ? "d" : "u", val));
}
printf ("[default]");
return;
}
-
+
switch (form)
{
case DW_FORM_block:
return;
}
- bfd_boolean is_signed =
+ bool is_signed =
(level > 0 && level <= MAX_CU_NESTING)
- ? level_type_signed [level - 1] : FALSE;
-
+ ? level_type_signed [level - 1] : false;
+
printf ("(");
while (uvalue)
{
default:
printf ("<corrupt>\n");
- warn (_("corrupt discr_list - unrecognised discriminant byte %#x\n"),
+ warn (_("corrupt discr_list - unrecognized discriminant byte %#x\n"),
discriminant);
return;
}
return data;
}
+ if (do_wide && ! do_loc)
+ {
+ /* PR 26847: Display the name of the form. */
+ const char * name = get_FORM_name (form);
+
+ /* For convenience we skip the DW_FORM_ prefix to the name. */
+ if (name[0] == 'D')
+ name += 8; /* strlen ("DW_FORM_") */
+ printf ("%c(%s)", delimiter, name);
+ }
+
switch (form)
{
default:
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:
SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
break;
+ case DW_FORM_strp_sup:
case DW_FORM_strp:
case DW_FORM_line_strp:
case DW_FORM_sec_offset:
case DW_FORM_ref1:
case DW_FORM_flag:
case DW_FORM_data1:
+ case DW_FORM_strx1:
+ case DW_FORM_addrx1:
SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end);
break;
case DW_FORM_ref2:
case DW_FORM_data2:
+ case DW_FORM_strx2:
+ case DW_FORM_addrx2:
SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
break;
+ case DW_FORM_strx3:
+ case DW_FORM_addrx3:
+ SAFE_BYTE_GET_AND_INC (uvalue, data, 3, end);
+ break;
+
+ case DW_FORM_ref_sup4:
case DW_FORM_ref4:
case DW_FORM_data4:
+ case DW_FORM_strx4:
+ case DW_FORM_addrx4:
SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
break;
break;
case DW_FORM_GNU_str_index:
+ case DW_FORM_strx:
case DW_FORM_ref_udata:
case DW_FORM_udata:
case DW_FORM_GNU_addr_index:
+ case DW_FORM_addrx:
READ_ULEB (uvalue, data, end);
break;
{
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));
+ {
+ if (do_wide)
+ /* We have already printed the form name. */
+ printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue));
+ else
+ printf ("%c<alt 0x%s>", delimiter, dwarf_vmatoa ("x", uvalue));
+ }
/* FIXME: Follow the reference... */
break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
+ case DW_FORM_ref_sup4:
case DW_FORM_ref_udata:
if (!do_loc)
printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset));
printf ("%c%s", delimiter, dwarf_vmatoa ("d", implicit_const));
break;
+ case DW_FORM_ref_sup8:
case DW_FORM_ref8:
case DW_FORM_data8:
if (!do_loc)
case DW_FORM_strp:
if (!do_loc)
- printf (_("%c(indirect string, offset: 0x%s): %s"), delimiter,
- dwarf_vmatoa ("x", uvalue),
- fetch_indirect_string (uvalue));
+ {
+ if (do_wide)
+ /* We have already displayed the form name. */
+ printf (_("%c(offset: 0x%s): %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_indirect_string (uvalue));
+ else
+ printf (_("%c(indirect string, offset: 0x%s): %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_indirect_string (uvalue));
+ }
break;
case DW_FORM_line_strp:
if (!do_loc)
- printf (_("%c(indirect line string, offset: 0x%s): %s"), delimiter,
- dwarf_vmatoa ("x", uvalue),
- fetch_indirect_line_string (uvalue));
+ {
+ if (do_wide)
+ /* We have already displayed the form name. */
+ printf (_("%c(offset: 0x%s): %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_indirect_line_string (uvalue));
+ else
+ printf (_("%c(indirect line string, offset: 0x%s): %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_indirect_line_string (uvalue));
+ }
break;
case DW_FORM_GNU_str_index:
+ case DW_FORM_strx:
+ case DW_FORM_strx1:
+ case DW_FORM_strx2:
+ case DW_FORM_strx3:
+ case DW_FORM_strx4:
if (!do_loc)
{
- const char * suffix = strrchr (section->name, '.');
- bfd_boolean dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? TRUE : FALSE;
+ const char *suffix = strrchr (section->name, '.');
+ bool dwo = suffix && strcmp (suffix, ".dwo") == 0;
- printf (_("%c(indexed string: 0x%s): %s"), delimiter,
- dwarf_vmatoa ("x", uvalue),
- fetch_indexed_string (uvalue, this_set, offset_size, dwo));
+ if (do_wide)
+ /* We have already displayed the form name. */
+ printf (_("%c(offset: 0x%s): %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_indexed_string (uvalue, this_set, offset_size, dwo));
+ else
+ printf (_("%c(indexed string: 0x%s): %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_indexed_string (uvalue, this_set, offset_size, dwo));
}
break;
case DW_FORM_GNU_strp_alt:
if (!do_loc)
{
- printf (_("%c(alt indirect string, offset: 0x%s) %s"), delimiter,
- dwarf_vmatoa ("x", uvalue),
- fetch_alt_indirect_string (uvalue));
+ if (do_wide)
+ /* We have already displayed the form name. */
+ printf (_("%c(offset: 0x%s) %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_alt_indirect_string (uvalue));
+ else
+ printf (_("%c(alt indirect string, offset: 0x%s) %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_alt_indirect_string (uvalue));
}
break;
char buf[64];
SAFE_BYTE_GET64 (data, &high_bits, &uvalue, end);
- printf ("%csignature: 0x%s", delimiter,
- dwarf_vmatoa64 (high_bits, uvalue, buf, sizeof (buf)));
+ if (do_wide)
+ /* We have already displayed the form name. */
+ printf ("%c: 0x%s", delimiter,
+ dwarf_vmatoa64 (high_bits, uvalue, buf, sizeof (buf)));
+ else
+ printf ("%csignature: 0x%s", delimiter,
+ dwarf_vmatoa64 (high_bits, uvalue, buf, sizeof (buf)));
}
data += 8;
break;
case DW_FORM_GNU_addr_index:
+ case DW_FORM_addrx:
+ case DW_FORM_addrx1:
+ case DW_FORM_addrx2:
+ case DW_FORM_addrx3:
+ case DW_FORM_addrx4:
if (!do_loc)
- printf (_("%c(addr_index: 0x%s): %s"), delimiter,
- dwarf_vmatoa ("x", uvalue),
- fetch_indexed_value (uvalue * pointer_size, pointer_size));
+ {
+ dwarf_vma base;
+ dwarf_vma offset;
+
+ if (debug_info_p == NULL)
+ base = 0;
+ else if (debug_info_p->addr_base == DEBUG_INFO_UNAVAILABLE)
+ base = 0;
+ else
+ base = debug_info_p->addr_base;
+
+ offset = base + uvalue * pointer_size;
+
+ if (do_wide)
+ /* We have already displayed the form name. */
+ printf (_("%c(index: 0x%s): %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_indexed_value (offset, pointer_size));
+ else
+ printf (_("%c(addr_index: 0x%s): %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_indexed_value (offset, pointer_size));
+ }
break;
+ case DW_FORM_strp_sup:
+ if (!do_loc)
+ printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset));
+ break;
+
default:
- warn (_("Unrecognized form: %lu\n"), form);
+ warn (_("Unrecognized form: 0x%lx\n"), form);
break;
}
break;
case DW_AT_GNU_addr_base:
+ case DW_AT_addr_base:
debug_info_p->addr_base = uvalue;
break;
switch (form)
{
case DW_FORM_strp:
- add_dwo_name ((const char *) fetch_indirect_string (uvalue));
+ add_dwo_name ((const char *) fetch_indirect_string (uvalue), cu_offset);
+ break;
+ case DW_FORM_GNU_strp_alt:
+ add_dwo_name ((const char *) fetch_alt_indirect_string (uvalue), cu_offset);
break;
case DW_FORM_GNU_str_index:
- add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, FALSE));
+ case DW_FORM_strx:
+ case DW_FORM_strx1:
+ case DW_FORM_strx2:
+ case DW_FORM_strx3:
+ case DW_FORM_strx4:
+ add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, false), cu_offset);
break;
case DW_FORM_string:
- add_dwo_name ((const char *) orig_data);
+ add_dwo_name ((const char *) orig_data, cu_offset);
break;
default:
warn (_("Unsupported form (%s) for attribute %s\n"),
break;
}
break;
-
+
case DW_AT_comp_dir:
/* FIXME: Also extract a build-id in a CU/TU. */
if (need_dwo_info)
switch (form)
{
case DW_FORM_strp:
- add_dwo_dir ((const char *) fetch_indirect_string (uvalue));
+ add_dwo_dir ((const char *) fetch_indirect_string (uvalue), cu_offset);
+ break;
+ case DW_FORM_GNU_strp_alt:
+ add_dwo_dir (fetch_alt_indirect_string (uvalue), cu_offset);
break;
case DW_FORM_line_strp:
- add_dwo_dir ((const char *) fetch_indirect_line_string (uvalue));
+ add_dwo_dir ((const char *) fetch_indirect_line_string (uvalue), cu_offset);
break;
case DW_FORM_GNU_str_index:
- add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, FALSE));
+ case DW_FORM_strx:
+ case DW_FORM_strx1:
+ case DW_FORM_strx2:
+ case DW_FORM_strx3:
+ case DW_FORM_strx4:
+ add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, false), cu_offset);
break;
case DW_FORM_string:
- add_dwo_dir ((const char *) orig_data);
+ add_dwo_dir ((const char *) orig_data, cu_offset);
break;
default:
warn (_("Unsupported form (%s) for attribute %s\n"),
break;
}
break;
-
+
case DW_AT_GNU_dwo_id:
if (need_dwo_info)
switch (form)
{
case DW_FORM_data8:
/* FIXME: Record the length of the ID as well ? */
- add_dwo_id ((const char *) (data - 8));
+ add_dwo_id ((const char *) (data - 8), cu_offset);
break;
default:
warn (_("Unsupported form (%s) for attribute %s\n"),
break;
}
break;
-
+
default:
break;
}
if (level >= 0 && level < MAX_CU_NESTING
&& uvalue < (size_t) (end - start))
{
- bfd_boolean is_signed = FALSE;
+ bool is_signed = false;
+ abbrev_entry *type_abbrev;
+ unsigned char *type_data;
+ unsigned long type_cu_offset;
- get_type_signedness (start, start + uvalue, end, pointer_size,
- offset_size, dwarf_version, & is_signed, FALSE);
+ 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_inline:
printf ("\t");
switch (uvalue)
printf ("\t");
display_discr_list (form, uvalue, data, end, level);
break;
-
+
case DW_AT_frame_base:
have_frame_base = 1;
/* Fall through. */
case DW_AT_import:
{
- if (form == DW_FORM_ref_sig8
- || form == DW_FORM_GNU_ref_alt)
- break;
+ unsigned long abbrev_number;
+ abbrev_entry *entry;
- if (form == DW_FORM_ref1
- || form == DW_FORM_ref2
- || form == DW_FORM_ref4
- || form == DW_FORM_ref_udata)
- uvalue += cu_offset;
-
- 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;
- unsigned char *p = section->start + uvalue;
-
- READ_ULEB (abbrev_number, p, 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 ("]");
}
}
following debug links, then attempt to load the requested section
from one of the separate debug info files. */
-static bfd_boolean
+static bool
load_debug_section_with_follow (enum dwarf_section_display_enum sec_enum,
void * handle)
{
}
}
- return TRUE;
+ return true;
}
if (do_follow_links)
/* FIXME: We should check to see if any of the remaining debug info
files also contain this section, and, umm, do something about it. */
- return TRUE;
+ return true;
}
}
}
- return FALSE;
+ return false;
}
static void
-introduce (struct dwarf_section * section, bfd_boolean raw)
+introduce (struct dwarf_section * section, bool raw)
{
if (raw)
{
printf (_("Contents of the %s section:\n\n"), section->name);
}
}
-
+
/* Process the contents of a .debug_info section.
If do_loc is TRUE then we are scanning for location lists and dwo tags
and we do not want to display anything to the user.
Returns TRUE upon success. Otherwise an error or warning message is
printed and FALSE is returned. */
-static bfd_boolean
-process_debug_info (struct dwarf_section * section,
- void * file,
- enum dwarf_section_display_enum abbrev_sec,
- bfd_boolean do_loc,
- bfd_boolean do_types)
+static bool
+process_debug_info (struct dwarf_section * section,
+ void *file,
+ enum dwarf_section_display_enum abbrev_sec,
+ bool do_loc,
+ bool do_types)
{
unsigned char *start = section->start;
unsigned char *end = start + section->size;
{
warn (_("Reserved length value (0x%s) found in section %s\n"),
dwarf_vmatoa ("x", length), section->name);
- return FALSE;
+ return false;
}
else
section_begin += length + 4;
{
warn (_("Corrupt unit length (0x%s) found in section %s\n"),
dwarf_vmatoa ("x", length), section->name);
- return FALSE;
+ return false;
}
}
if (num_units == 0)
{
error (_("No comp units in %s section ?\n"), section->name);
- return FALSE;
+ return false;
}
/* Then allocate an array to hold the information. */
error (_("Not enough memory for a debug info array of %u entries\n"),
num_units);
alloc_num_debug_info_entries = num_debug_info_entries = 0;
- return FALSE;
+ return false;
}
/* PR 17531: file: 92ca3797.
{
warn (_("Unable to locate %s section!\n"),
debug_displays [abbrev_sec].section.uncompressed_name);
- return FALSE;
+ return false;
}
if (!do_loc && dwarf_start_die == 0)
- introduce (section, FALSE);
-
- for (section_begin = start, unit = 0; start < end; unit++)
+ introduce (section, false);
+
+ free_all_abbrevs ();
+ free (cu_abbrev_map);
+ cu_abbrev_map = NULL;
+ next_free_abbrev_map_entry = 0;
+
+ /* 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 (compunit.cu_unit_type == DW_UT_split_compile
+ || compunit.cu_unit_type == DW_UT_skeleton)
+ {
+ uint64_t dwo_id;
+ SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, 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 (compunit.cu_version < 5)
SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end);
+ bool do_dwo_id = false;
+ uint64_t dwo_id = 0;
+ if (compunit.cu_unit_type == DW_UT_split_compile
+ || compunit.cu_unit_type == DW_UT_skeleton)
+ {
+ SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end);
+ do_dwo_id = true;
+ }
+
/* PR 17512: file: 001-108546-0.001:0.1. */
if (compunit.cu_pointer_size < 2 || compunit.cu_pointer_size > 8)
{
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);
printf (_(" Type Offset: 0x%s\n"),
dwarf_vmatoa ("x", type_offset));
}
+ if (do_dwo_id)
+ printf (_(" DWO ID: 0x%s\n"), dwarf_vmatoa ("x", dwo_id));
if (this_set != NULL)
{
dwarf_vma *offsets = this_set->section_offsets;
}
if (compunit.cu_unit_type != DW_UT_compile
- && compunit.cu_unit_type != DW_UT_type)
+ && compunit.cu_unit_type != DW_UT_partial
+ && compunit.cu_unit_type != DW_UT_type
+ && compunit.cu_unit_type != DW_UT_split_compile
+ && compunit.cu_unit_type != DW_UT_skeleton)
{
warn (_("CU at offset %s contains corrupt or "
"unsupported unit type: %d.\n"),
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;
}
}
if (dwarf_start_die != 0 && level < saved_level)
- return TRUE;
+ return true;
continue;
}
/* 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)
}
warn (_("DIE at offset 0x%lx refers to abbreviation number %lu which does not exist\n"),
die_offset, abbrev_number);
- return FALSE;
+ return false;
}
if (!do_loc && do_printing)
if (!do_loc)
printf ("\n");
- return TRUE;
+ return true;
}
/* Locate and scan the .debug_info section in the file and record the pointer
(void) load_cu_tu_indexes (file);
if (load_debug_section_with_follow (info, file)
- && process_debug_info (&debug_displays [info].section, file, abbrev, TRUE, FALSE))
+ && process_debug_info (&debug_displays [info].section, file, abbrev, true, false))
return num_debug_info_entries;
if (load_debug_section_with_follow (info_dwo, file)
&& process_debug_info (&debug_displays [info_dwo].section, file,
- abbrev_dwo, TRUE, FALSE))
+ abbrev_dwo, true, false))
return num_debug_info_entries;
num_debug_info_entries = DEBUG_INFO_UNAVAILABLE;
{
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;
}
}
}
static unsigned char *
-display_formatted_table (unsigned char * data,
- unsigned char * start,
- unsigned char * end,
- const DWARF2_Internal_LineInfo * linfo,
- struct dwarf_section * section,
- bfd_boolean is_dir)
+display_formatted_table (unsigned char *data,
+ unsigned char *start,
+ unsigned char *end,
+ const DWARF2_Internal_LineInfo *linfo,
+ struct dwarf_section *section,
+ bool is_dir)
{
unsigned char *format_start, format_count, *format, formati;
dwarf_vma data_count, datai;
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++)
{
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;
}
}
READ_ULEB (data_count, data, end);
- if (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. */
+ /* Delay displaying name as the last entry for better screen layout. */
for (namepass = 0; namepass < 2; namepass++)
{
format = format_start;
printf (_("\tSize"));
break;
case DW_LNCT_MD5:
- printf (_("\tMD5"));
+ printf (_("\tMD5\t\t\t"));
break;
default:
printf (_("\t(Unknown format content type %s)"),
unsigned char *datapass = data;
printf (" %d", last_entry++);
- /* Delay displaying name as the last entry for better screen layout. */
+ /* Delay displaying name as the last entry for better screen layout. */
for (namepass = 0; namepass < 2; namepass++)
{
format = format_start;
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');
return data;
}
+static int
+display_debug_sup (struct dwarf_section * section,
+ void * file ATTRIBUTE_UNUSED)
+{
+ unsigned char * start = section->start;
+ unsigned char * end = section->start + section->size;
+ unsigned int version;
+ char is_supplementary;
+ const unsigned char * sup_filename;
+ size_t sup_filename_len;
+ unsigned int num_read;
+ int status;
+ dwarf_vma checksum_len;
+
+
+ introduce (section, true);
+ if (section->size < 4)
+ {
+ error (_("corrupt .debug_sup section: size is too small\n"));
+ return 0;
+ }
+
+ /* Read the data. */
+ SAFE_BYTE_GET_AND_INC (version, start, 2, end);
+ if (version < 5)
+ warn (_("corrupt .debug_sup section: version < 5"));
+
+ SAFE_BYTE_GET_AND_INC (is_supplementary, start, 1, end);
+ if (is_supplementary != 0 && is_supplementary != 1)
+ warn (_("corrupt .debug_sup section: is_supplementary not 0 or 1\n"));
+
+ sup_filename = start;
+ if (is_supplementary && sup_filename[0] != 0)
+ warn (_("corrupt .debug_sup section: filename not empty in supplementary section\n"));
+
+ sup_filename_len = strnlen ((const char *) start, end - start);
+ if (sup_filename_len == (size_t) (end - start))
+ {
+ error (_("corrupt .debug_sup section: filename is not NUL terminated\n"));
+ return 0;
+ }
+ start += sup_filename_len + 1;
+
+ checksum_len = read_leb128 (start, end, false /* unsigned */, & num_read, & status);
+ if (status)
+ {
+ error (_("corrupt .debug_sup section: bad LEB128 field for checksum length\n"));
+ checksum_len = 0;
+ }
+ start += num_read;
+ if (checksum_len > (dwarf_vma) (end - start))
+ {
+ error (_("corrupt .debug_sup section: checksum length is longer than the remaining section length\n"));
+ checksum_len = end - start;
+ }
+ else if (checksum_len < (dwarf_vma) (end - start))
+ {
+ warn (_("corrupt .debug_sup section: there are 0x%lx extra, unused bytes at the end of the section\n"),
+ (long) ((end - start) - checksum_len));
+ }
+
+ printf (_(" Version: %u\n"), version);
+ printf (_(" Is Supp: %u\n"), is_supplementary);
+ printf (_(" Filename: %s\n"), sup_filename);
+ printf (_(" Checksum Len: %lu\n"), (long) checksum_len);
+ if (checksum_len > 0)
+ {
+ printf (_(" Checksum: "));
+ while (checksum_len--)
+ printf ("0x%x ", * start++ );
+ printf ("\n");
+ }
+ return 1;
+}
+
static int
display_debug_lines_raw (struct dwarf_section * section,
unsigned char * data,
unsigned char *start = section->start;
int verbose_view = 0;
- introduce (section, TRUE);
+ introduce (section, true);
while (data < end)
{
unsigned char *end_of_sequence;
int i;
- if (const_strneq (section->name, ".debug_line.")
+ if (startswith (section->name, ".debug_line.")
/* Note: the following does not apply to .debug_line.dwo sections.
These are full debug_line sections. */
&& strcmp (section->name, ".debug_line.dwo") != 0)
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)
load_debug_section_with_follow (line_str, file);
data = display_formatted_table (data, start, end, &linfo, section,
- TRUE);
+ true);
data = display_formatted_table (data, start, end, &linfo, section,
- FALSE);
+ false);
}
else
{
{
static DWARF2_Internal_LineInfo saved_linfo;
- introduce (section, FALSE);
+ introduce (section, false);
while (data < end)
{
unsigned char **directory_table = NULL;
dwarf_vma n_directories = 0;
- if (const_strneq (section->name, ".debug_line.")
+ if (startswith (section->name, ".debug_line.")
/* Note: the following does not apply to .debug_line.dwo sections.
These are full debug_line sections. */
&& strcmp (section->name, ".debug_line.dwo") != 0)
/* 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++)
{
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++)
{
/* 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_ULEB (n_files, data, end);
- if (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++)
{
/* 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;
}
default:
printf (_("UNKNOWN (%u): length %ld\n"),
- ext_op_code, op_code_data - data);
+ ext_op_code, (long int) (op_code_data - data));
break;
}
data = op_code_end;
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++;
we test for that later on. */
load_debug_info (file);
- introduce (section, FALSE);
+ introduce (section, false);
while (start < end)
{
unsigned char *curr = start;
enum dwarf_macinfo_record_type op;
- introduce (section, FALSE);
+ introduce (section, false);
while (curr < end)
{
unsigned char *end = start + section->size;
unsigned char *curr = start;
unsigned char *extended_op_buf[256];
+ bool is_dwo = false;
+ const char *suffix = strrchr (section->name, '.');
+
+ if (suffix && strcmp (suffix, ".dwo") == 0)
+ is_dwo = true;
load_debug_section_with_follow (str, file);
load_debug_section_with_follow (line, file);
-
- introduce (section, FALSE);
+ load_debug_section_with_follow (str_index, file);
+
+ introduce (section, false);
while (curr < end)
{
unsigned int lineno, version, flags;
- unsigned int offset_size = 4;
+ unsigned int offset_size;
const unsigned char *string;
dwarf_vma line_offset = 0, sec_offset = curr - start, offset;
unsigned char **extended_ops = NULL;
SAFE_BYTE_GET_AND_INC (version, curr, 2, end);
if (version != 4 && version != 5)
{
- error (_("Only GNU extension to DWARF 4 or 5 of %s is currently supported.\n"),
- section->name);
+ error (_("Expected to find a version number of 4 or 5 in section %s but found %d instead\n"),
+ section->name, version);
return 0;
}
SAFE_BYTE_GET_AND_INC (flags, curr, 1, end);
- if (flags & 1)
- offset_size = 8;
+ offset_size = (flags & 1) ? 8 : 4;
printf (_(" Offset: 0x%lx\n"),
(unsigned long) sec_offset);
printf (_(" Version: %d\n"), version);
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;
lineno, filenum,
dir_name != NULL ? (const char *) dir_name : "",
dir_name != NULL ? "/" : "", file_name);
- }
- break;
-
- case DW_MACRO_end_file:
- printf (_(" DW_MACRO_end_file\n"));
- break;
-
- 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);
+ case DW_MACRO_end_file:
+ printf (_(" DW_MACRO_end_file\n"));
break;
case DW_MACRO_define_strp:
READ_ULEB (lineno, curr, end);
- SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
+ if (version == 4 && is_dwo)
+ READ_ULEB (offset, curr, end);
+ else
+ 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"),
lineno, string);
case DW_MACRO_undef_strp:
READ_ULEB (lineno, curr, end);
- SAFE_BYTE_GET_AND_INC (offset, curr, offset_size, end);
+ if (version == 4 && is_dwo)
+ READ_ULEB (offset, curr, end);
+ else
+ 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"),
lineno, string);
(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);
{
abbrev_entry *entry;
unsigned char *start = section->start;
- unsigned char *end = start + section->size;
+ const unsigned char *end = start + section->size;
- introduce (section, FALSE);
+ 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"));
/* Return true when ADDR is the maximum address, when addresses are
POINTER_SIZE bytes long. */
-static bfd_boolean
+static bool
is_max_address (dwarf_vma addr, unsigned int pointer_size)
{
dwarf_vma mask = ~(~(dwarf_vma) 1 << (pointer_size * 8 - 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);
break;
case DW_LLE_offset_pair:
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,
}
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)
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 char *next = start, *vnext = vstart;
unsigned int *array = NULL;
const char *suffix = strrchr (section->name, '.');
- bfd_boolean is_dwo = FALSE;
+ bool is_dwo = false;
int is_loclists = strstr (section->name, "debug_loclists") != NULL;
dwarf_vma expected_start = 0;
if (suffix && strcmp (suffix, ".dwo") == 0)
- is_dwo = TRUE;
+ is_dwo = true;
bytes = section->size;
if (!locs_sorted)
array = (unsigned int *) xcmalloc (num_loc_list, sizeof (unsigned int));
- introduce (section, FALSE);
+ introduce (section, false);
if (reloc_at (section, 0))
printf (_(" Warning: This section has relocations - addresses seen here may not be accurate.\n\n"));
return 0;
}
- introduce (section, FALSE);
+ introduce (section, false);
while (bytes)
{
static int
display_debug_info (struct dwarf_section *section, void *file)
{
- return process_debug_info (section, file, section->abbrev_sec, FALSE, FALSE);
+ return process_debug_info (section, file, section->abbrev_sec, false, false);
}
static int
display_debug_types (struct dwarf_section *section, void *file)
{
- return process_debug_info (section, file, section->abbrev_sec, FALSE, TRUE);
+ return process_debug_info (section, file, section->abbrev_sec, false, true);
}
static int
display_trace_info (struct dwarf_section *section, void *file)
{
- return process_debug_info (section, file, section->abbrev_sec, FALSE, TRUE);
+ return process_debug_info (section, file, section->abbrev_sec, false, true);
}
static int
unsigned char *start = section->start;
unsigned char *end = start + section->size;
- introduce (section, FALSE);
+ introduce (section, false);
/* It does not matter if this load fails,
we test for that later on. */
unsigned char *end;
unsigned int i;
unsigned int count;
+ unsigned char * header;
if (section->size == 0)
{
return 0;
}
- introduce (section, FALSE);
+ introduce (section, false);
/* PR 17531: file: cf38d01b.
We use xcalloc because a corrupt file may not have initialised all of the
debug_addr_info [count]->addr_base = section->size;
qsort (debug_addr_info, count, sizeof (debug_info *), comp_addr_base);
+ header = section->start;
for (i = 0; i < count; i++)
{
unsigned int idx;
printf (_("\tIndex\tAddress\n"));
entry = section->start + debug_addr_info [i]->addr_base;
- end = section->start + debug_addr_info [i + 1]->addr_base;
+ if (debug_addr_info [i]->dwarf_version >= 5)
+ {
+ size_t header_size = entry - header;
+ unsigned char * curr_header = header;
+ dwarf_vma length;
+ int version;
+ int segment_selector_size;
+
+ if (header_size != 8 && header_size != 16)
+ {
+ warn (_("Corrupt %s section: expecting header size of 8 or 16, but found %ld instead\n"),
+ section->name, (long) header_size);
+ return 0;
+ }
+
+ SAFE_BYTE_GET_AND_INC (length, curr_header, 4, entry);
+ if (length == 0xffffffff)
+ SAFE_BYTE_GET (length, curr_header, 8, entry);
+ end = curr_header + length;
+
+ SAFE_BYTE_GET_AND_INC (version, curr_header, 2, entry);
+ if (version != 5)
+ warn (_("Corrupt %s section: expecting version number 5 in header but found %d instead\n"),
+ section->name, version);
+
+ SAFE_BYTE_GET_AND_INC (address_size, curr_header, 1, entry);
+ SAFE_BYTE_GET_AND_INC (segment_selector_size, curr_header, 1, entry);
+ address_size += segment_selector_size;
+ }
+ else
+ end = section->start + debug_addr_info [i + 1]->addr_base;
+ header = end;
idx = 0;
while (entry < end)
{
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, '.');
+ bool dwo = suffix && strcmp (suffix, ".dwo") == 0;
+
+ 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;
+
+ unsigned char *entries_end;
+ 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;
+ entries_end = end;
+
+ printf (_(" Length: %#lx\n"), (unsigned long) length);
+ printf (_(" Index Offset [String]\n"));
+ }
+ else
+ {
+ entries_end = curr + length;
+
+ 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; curr < entries_end; idx++)
+ {
+ dwarf_vma offset;
+ const unsigned char * string;
+
+ if (curr + entry_length > entries_end)
+ /* Not enough space to read one entry_length, give up. */
+ return 0;
+
+ 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;
}
break;
SAFE_SIGNED_BYTE_GET_AND_INC (end, start, pointer_size, finish);
-
printf (" %8.8lx ", offset);
if (begin == 0 && end == 0)
if (rlet == DW_RLE_base_address)
continue;
- print_dwarf_vma (begin + base_address, pointer_size);
- print_dwarf_vma (end + base_address, pointer_size);
+ /* Only a DW_RLE_offset_pair needs the base address added. */
+ if (rlet == DW_RLE_offset_pair)
+ {
+ begin += base_address;
+ end += base_address;
+ }
+
+ print_dwarf_vma (begin, pointer_size);
+ print_dwarf_vma (end, pointer_size);
if (begin == end)
fputs (_("(start == end)"), stdout);
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)
{
num_range_list = 0;
for (i = 0; i < num_debug_info_entries; i++)
- num_range_list += debug_information [i].num_range_lists;
+ {
+ if (debug_information [i].dwarf_version < 5 && is_rnglists)
+ /* Skip .debug_rnglists reference. */
+ continue;
+ if (debug_information [i].dwarf_version >= 5 && !is_rnglists)
+ /* Skip .debug_range reference. */
+ continue;
+ num_range_list += debug_information [i].num_range_lists;
+ }
if (num_range_list == 0)
{
debug_info *debug_info_p = &debug_information[i];
unsigned int j;
+ if (debug_information [i].dwarf_version < 5 && is_rnglists)
+ /* Skip .debug_rnglists reference. */
+ continue;
+ if (debug_information [i].dwarf_version >= 5 && !is_rnglists)
+ /* Skip .debug_range reference. */
+ continue;
+
for (j = 0; j < debug_info_p->num_range_lists; j++)
{
range_entry_fill->ranges_offset = debug_info_p->range_lists[j];
warn (_("Range lists in %s section start at 0x%lx\n"),
section->name, (unsigned long) range_entries[0].ranges_offset);
- introduce (section, FALSE);
+ introduce (section, false);
printf (_(" Offset Begin End\n"));
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)
document. */
switch (regno)
{
-#define DECLARE_CSR(NAME,VALUE) case VALUE + 4096: name = #NAME; break;
+#define DECLARE_CSR(NAME,VALUE,CLASS,DEFINE_VER,ABORT_VER) \
+ case VALUE + 4096: name = #NAME; break;
#include "opcode/riscv-opc.h"
#undef DECLARE_CSR
{
case bfd_mach_x86_64:
case bfd_mach_x86_64_intel_syntax:
- case bfd_mach_x86_64_nacl:
case bfd_mach_x64_32:
case bfd_mach_x64_32_intel_syntax:
- case bfd_mach_x64_32_nacl:
init_dwarf_regnames_x86_64 ();
break;
if (*need_col_headers)
{
- static const char *sloc = " LOC";
-
*need_col_headers = 0;
- printf ("%-*s CFA ", eh_addr_size * 2, sloc);
+ printf ("%-*s CFA ", eh_addr_size * 2, " LOC");
for (r = 0; r < *max_regs; r++)
if (fc->col_type[r] != DW_CFA_unreferenced)
Frame_Chunk *chunks = NULL, *forward_refs = NULL;
Frame_Chunk *remembered_state = NULL;
Frame_Chunk *rs;
- bfd_boolean is_eh = strcmp (section->name, ".eh_frame") == 0;
+ bool is_eh = strcmp (section->name, ".eh_frame") == 0;
unsigned int max_regs = 0;
const char *bad_reg = _("bad register: ");
unsigned int saved_eh_addr_size = eh_addr_size;
- introduce (section, FALSE);
+ introduce (section, false);
while (start < end)
{
unsigned int encoded_ptr_size = saved_eh_addr_size;
unsigned int offset_size;
unsigned int initial_length_size;
- bfd_boolean all_nops;
+ bool 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)
start = tmp;
}
- all_nops = TRUE;
+ all_nops = true;
/* Now we know what registers are used, make a second pass over
the chunk, this time actually printing out the info. */
/* Make a note if something other than DW_CFA_nop happens. */
if (op != DW_CFA_nop)
- all_nops = FALSE;
+ all_nops = false;
/* Warning: if you add any more cases to this switch, be
sure to add them to the corresponding switch above. */
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;
}
const unsigned char *const section_end = section->start + section->size;
unsigned char *unit_end;
- introduce (section, FALSE);
+ introduce (section, false);
load_debug_section_with_follow (str, file);
uint32_t augmentation_string_size;
unsigned int i;
unsigned long sec_off;
- bfd_boolean augmentation_printable;
+ bool augmentation_printable;
const char *augmentation_string;
unit_start = hdrptr;
printf (_("Augmentation string:"));
- augmentation_printable = TRUE;
+ augmentation_printable = true;
augmentation_string = (const char *) hdrptr;
for (i = 0; i < augmentation_string_size; i++)
printf (" %02x", uc);
if (uc != 0 && !ISPRINT (uc))
- augmentation_printable = FALSE;
+ augmentation_printable = false;
}
if (augmentation_printable)
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;
const unsigned char * filename;
unsigned int filelen;
- introduce (section, FALSE);
+ introduce (section, false);
/* The .gnu_debuglink section is formatted as:
(c-string) Filename.
The .gun_debugaltlink section is formatted as:
(c-string) Filename.
(binary) Build-ID. */
-
+
filename = section->start;
filelen = strnlen ((const char *) filename, section->size);
if (filelen == section->size)
printf (_(" Separate debug info file: %s\n"), filename);
- if (const_strneq (section->name, ".gnu_debuglink"))
+ if (startswith (section->name, ".gnu_debuglink"))
{
unsigned int crc32;
unsigned int crc_offset;
return 0;
}
}
- else /* const_strneq (section->name, ".gnu_debugaltlink") */
+ else /* startswith (section->name, ".gnu_debugaltlink") */
{
const unsigned char * build_id = section->start + filelen + 1;
bfd_size_type build_id_len = section->size - (filelen + 1);
/* The documentation for the format of this file is in gdb/dwarf2read.c. */
- introduce (section, FALSE);
+ introduce (section, false);
if (section->size < 6 * sizeof (uint32_t))
{
if (do_display)
{
- introduce (section, FALSE);
+ introduce (section, false);
printf (_(" Version: %u\n"), version);
if (version >= 2)
unsigned char *poffsets = ppool + (size_t) ncols * 4;
unsigned char *psizes = poffsets + (size_t) nused * ncols * 4;
unsigned char *pend = psizes + (size_t) nused * ncols * 4;
- bfd_boolean is_tu_index;
+ bool is_tu_index;
struct cu_tu_set *this_set = NULL;
unsigned int row;
unsigned char *prow;
return 1;
}
+static int cu_tu_indexes_read = -1; /* Tri-state variable. */
+
/* Load the CU and TU indexes if present. This will build a list of
section sets that we can use to associate a .debug_info.dwo section
with its associated .debug_abbrev.dwo section in a .dwp file. */
-static bfd_boolean
+static bool
load_cu_tu_indexes (void *file)
{
- static int cu_tu_indexes_read = -1; /* Tri-state variable. */
-
/* If we have already loaded (or tried to load) the CU and TU indexes
then do not bother to repeat the task. */
if (cu_tu_indexes_read == -1)
{
- cu_tu_indexes_read = TRUE;
-
+ cu_tu_indexes_read = true;
+
if (load_debug_section_with_follow (dwp_cu_index, file))
if (! process_cu_tu_index (&debug_displays [dwp_cu_index].section, 0))
- cu_tu_indexes_read = FALSE;
+ cu_tu_indexes_read = false;
if (load_debug_section_with_follow (dwp_tu_index, file))
if (! process_cu_tu_index (&debug_displays [dwp_tu_index].section, 0))
- cu_tu_indexes_read = FALSE;
+ cu_tu_indexes_read = false;
}
- return (bfd_boolean) cu_tu_indexes_read;
+ return (bool) cu_tu_indexes_read;
}
/* Find the set of sections that includes section SHNDX. */
return ~crc & 0xffffffff;
}
-typedef bfd_boolean (* check_func_type) (const char *, void *);
-typedef const char * (* parse_func_type) (struct dwarf_section *, void *);
+typedef bool (*check_func_type) (const char *, void *);
+typedef const char *(* parse_func_type) (struct dwarf_section *, void *);
-static bfd_boolean
+static bool
check_gnu_debuglink (const char * pathname, void * crc_pointer)
{
static unsigned char buffer [8 * 1024];
sep_data = open_debug_file (pathname);
if (sep_data == NULL)
- return FALSE;
+ return false;
/* Yes - we are opening the file twice... */
f = fopen (pathname, "rb");
/* Paranoia: This should never happen. */
close_debug_file (sep_data);
warn (_("Unable to reopen separate debug info file: %s\n"), pathname);
- return FALSE;
+ return false;
}
while ((count = fread (buffer, 1, sizeof (buffer), f)) > 0)
close_debug_file (sep_data);
warn (_("Separate debug info file %s found, but CRC does not match - ignoring\n"),
pathname);
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
static const char *
The CRC value is stored after the filename, aligned up to 4 bytes. */
name = (const char *) section->start;
-
crc_offset = strnlen (name, section->size) + 1;
crc_offset = (crc_offset + 3) & ~3;
if (crc_offset + 4 > section->size)
return name;
}
-static bfd_boolean
+static bool
check_gnu_debugaltlink (const char * filename, void * data ATTRIBUTE_UNUSED)
{
void * sep_data = open_debug_file (filename);
if (sep_data == NULL)
- return FALSE;
+ return false;
/* FIXME: We should now extract the build-id in the separate file
and check it... */
- return TRUE;
+ return true;
}
typedef struct build_id_data
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 bool
+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.
This should duplicate the logic in bfd/opncls.c:find_separate_debug_file(). */
canon_dir = lrealpath (main_filename);
-
+
for (canon_dirlen = strlen (canon_dir); canon_dirlen > 0; canon_dirlen--)
if (IS_DIR_SEPARATOR (canon_dir[canon_dirlen - 1]))
break;
if (check_func (debug_filename, func_data))
goto found;
- /* Failed to find the file. */
- warn (_("could not find separate debug file '%s'\n"), separate_filename);
- warn (_("tried: %s\n"), debug_filename);
+#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
+
+ if (do_debug_links)
+ {
+ /* Failed to find the file. */
+ warn (_("could not find separate debug file '%s'\n"),
+ separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
#ifdef EXTRA_DEBUG_ROOT2
- sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT2, separate_filename);
- warn (_("tried: %s\n"), debug_filename);
+ sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT2,
+ separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
#endif
#ifdef EXTRA_DEBUG_ROOT1
- sprintf (debug_filename, "%s/%s/%s", EXTRA_DEBUG_ROOT1, canon_dir, separate_filename);
- warn (_("tried: %s\n"), debug_filename);
+ sprintf (debug_filename, "%s/%s/%s", EXTRA_DEBUG_ROOT1,
+ canon_dir, separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
- sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT1, separate_filename);
- warn (_("tried: %s\n"), debug_filename);
+ sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT1,
+ separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
#endif
- sprintf (debug_filename, "%s.debug/%s", canon_dir, separate_filename);
- warn (_("tried: %s\n"), debug_filename);
+ sprintf (debug_filename, "%s.debug/%s", canon_dir,
+ separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
- sprintf (debug_filename, "%s%s", canon_dir, separate_filename);
- warn (_("tried: %s\n"), debug_filename);
+ sprintf (debug_filename, "%s%s", canon_dir, separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
- sprintf (debug_filename, ".debug/%s", separate_filename);
- warn (_("tried: %s\n"), debug_filename);
+ sprintf (debug_filename, ".debug/%s", separate_filename);
+ warn (_("tried: %s\n"), debug_filename);
- sprintf (debug_filename, "%s", 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);
{
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
files that would also match. */
- printf (_("%s: Found separate debug info file: %s\n\n"), main_filename, debug_filename);
+ if (do_debug_links)
+ printf (_("\n%s: Found separate debug info file: %s\n"), main_filename, debug_filename);
add_separate_debug_file (debug_filename, debug_handle);
/* Do not free debug_filename - it might be referenced inside
char * separate_filename;
void * separate_handle;
- /* FIXME: Skip adding / if dwo_dir ends in /. */
- separate_filename = concat (dir, "/", name, NULL);
+ if (IS_ABSOLUTE_PATH (name))
+ separate_filename = strdup (name);
+ else
+ /* FIXME: Skip adding / if dwo_dir ends in /. */
+ separate_filename = concat (dir, "/", name, NULL);
if (separate_filename == NULL)
{
warn (_("Out of memory allocating dwo filename\n"));
return separate_handle;
}
+static void
+load_debug_sup_file (const char * main_filename, void * file)
+{
+ if (! load_debug_section (debug_sup, file))
+ return; /* No .debug_sup section. */
+
+ struct dwarf_section * section;
+ section = & debug_displays [debug_sup].section;
+ assert (section != NULL);
+
+ if (section->start == NULL || section->size < 5)
+ {
+ warn (_(".debug_sup section is corrupt/empty\n"));
+ return;
+ }
+
+ if (section->start[2] != 0)
+ return; /* This is a supplementary file. */
+
+ const char * filename = (const char *) section->start + 3;
+ if (strnlen (filename, section->size - 3) == section->size - 3)
+ {
+ warn (_("filename in .debug_sup section is corrupt\n"));
+ return;
+ }
+
+ if (filename[0] != '/' && strchr (main_filename, '/'))
+ {
+ char * new_name;
+ if (asprintf (& new_name, "%.*s/%s",
+ (int) (strrchr (main_filename, '/') - main_filename),
+ main_filename,
+ filename) < 3)
+ warn (_("unable to construct path for supplementary debug file"));
+ else
+ filename = new_name;
+ }
+
+ void * handle;
+ handle = open_debug_file (filename);
+ if (handle == NULL)
+ {
+ warn (_("unable to open file '%s' referenced from .debug_sup section\n"), filename);
+ return;
+ }
+
+ printf (_("%s: Found supplementary debug file: %s\n\n"), main_filename, filename);
+
+ /* FIXME: Compare the checksums, if present. */
+ add_separate_debug_file (filename, handle);
+}
+
+/* Load a debuglink section and/or a debugaltlink section, if either are present.
+ Recursively check the loaded files for more of these sections.
+ Also follow any links in .debug_sup sections.
+ FIXME: Should also check for DWO_* entries in the newly 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_debug_sup_file (filename, file);
+}
+
/* 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
will be populated with open file handles. */
-bfd_boolean
+bool
load_separate_debug_files (void * file, const char * filename)
{
/* Skip this operation if we are not interested in debug links. */
if (! do_follow_links && ! do_debug_links)
- return FALSE;
+ return false;
/* See if there are any dwo links. */
if (load_debug_section (str, file)
{
free_dwo_info ();
- if (process_debug_info (& debug_displays[info].section, file, abbrev, TRUE, FALSE))
+ if (process_debug_info (& debug_displays[info].section, file, abbrev,
+ true, false))
{
- bfd_boolean introduced = FALSE;
- dwo_info * dwinfo;
- const char * dir = NULL;
- const char * id = NULL;
+ bool introduced = false;
+ dwo_info *dwinfo;
+ const char *dir = NULL;
+ const char *id = NULL;
+ const char *name = NULL;
for (dwinfo = first_dwo_info; dwinfo != NULL; dwinfo = dwinfo->next)
{
+ /* Accumulate NAME, DIR and ID fields. */
switch (dwinfo->type)
{
case DWO_NAME:
+ if (name != NULL)
+ warn (_("Multiple DWO_NAMEs encountered for the same CU\n"));
+ name = dwinfo->value;
+ break;
+
+ case DWO_DIR:
+ /* There can be multiple DW_AT_comp_dir entries in a CU,
+ so do not complain. */
+ dir = dwinfo->value;
+ break;
+
+ case DWO_ID:
+ if (id != NULL)
+ warn (_("multiple DWO_IDs encountered for the same CU\n"));
+ id = dwinfo->value;
+ break;
+
+ default:
+ error (_("Unexpected DWO INFO type"));
+ break;
+ }
+
+ /* If we have reached the end of our list, or we are changing
+ CUs, then display the information that we have accumulated
+ so far. */
+ if (name != NULL
+ && (dwinfo->next == NULL
+ || dwinfo->next->cu_offset != dwinfo->cu_offset))
+ {
if (do_debug_links)
{
if (! introduced)
{
printf (_("The %s section contains link(s) to dwo file(s):\n\n"),
debug_displays [info].section.uncompressed_name);
- introduced = TRUE;
+ introduced = true;
}
- printf (_(" Name: %s\n"), dwinfo->value);
+ printf (_(" Name: %s\n"), name);
printf (_(" Directory: %s\n"), dir ? dir : _("<not-found>"));
if (id != NULL)
display_data (printf (_(" ID: ")), (unsigned char *) id, 8);
else
- printf (_(" ID: <unknown>\n"));
+ printf (_(" ID: <not specified>\n"));
printf ("\n\n");
}
if (do_follow_links)
- load_dwo_file (filename, dwinfo->value, dir, id);
- break;
-
- case DWO_DIR:
- dir = dwinfo->value;
- break;
-
- case DWO_ID:
- id = dwinfo->value;
- break;
+ load_dwo_file (filename, name, dir, id);
- default:
- error (_("Unexpected DWO INFO type"));
- break;
+ name = dir = id = NULL;
}
}
}
if (! do_follow_links)
/* The other debug links will be displayed by display_debug_links()
so we do not need to do any further processing here. */
- return FALSE;
+ 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;
+ return true;
do_follow_links = 0;
- return FALSE;
-}
+ return false;
+}
void
free_debug_memory (void)
{
unsigned int i;
- free_abbrevs ();
+ free_all_abbrevs ();
+
+ free (cu_abbrev_map);
+ cu_abbrev_map = NULL;
+ next_free_abbrev_map_entry = 0;
+
+ free (shndx_pool);
+ shndx_pool = NULL;
+ shndx_pool_size = 0;
+ shndx_pool_used = 0;
+ free (cu_sets);
+ cu_sets = NULL;
+ cu_count = 0;
+ free (tu_sets);
+ tu_sets = NULL;
+ tu_count = 0;
+
+ memset (level_type_signed, 0, sizeof level_type_signed);
+ cu_tu_indexes_read = -1;
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;
free ((void *) d);
}
first_separate_info = NULL;
-
+
free_dwo_info ();
}
{ "links", & do_debug_links, 1 },
{ "loc", & do_debug_loc, 1 },
{ "macro", & do_debug_macinfo, 1 },
+ { "no-follow-links", & do_follow_links, 0 },
{ "pubnames", & do_debug_pubnames, 1 },
{ "pubtypes", & do_debug_pubtypes, 1 },
/* This entry is for compatibility
{ "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 },
if (strncmp (p, entry->option, len) == 0
&& (p[len] == ',' || p[len] == '\0'))
{
- * entry->variable |= entry->val;
+ * entry->variable = entry->val;
/* The --debug-dump=frames-interp option also
enables the --debug-dump=frames option. */
case 'g': do_gdb_index = 1; break;
case 'i': do_debug_info = 1; break;
case 'K': do_follow_links = 1; break;
+ case 'N': do_follow_links = 0; break;
case 'k': do_debug_links = 1; break;
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
-#define ABBREV(N) NULL, NULL, NULL, 0, 0, N, NULL, 0, NULL
+#define NO_ABBREVS NULL, NULL, NULL, 0, 0, 0, NULL, 0
+#define ABBREV(N) NULL, NULL, NULL, 0, 0, N, NULL, 0
/* N.B. The order here must match the order in section_display_enum. */
struct dwarf_section_display debug_displays[] =
{
- { { ".debug_abbrev", ".zdebug_abbrev", NO_ABBREVS }, display_debug_abbrev, &do_debug_abbrevs, FALSE },
- { { ".debug_aranges", ".zdebug_aranges", NO_ABBREVS }, display_debug_aranges, &do_debug_aranges, TRUE },
- { { ".debug_frame", ".zdebug_frame", NO_ABBREVS }, display_debug_frames, &do_debug_frames, TRUE },
- { { ".debug_info", ".zdebug_info", ABBREV (abbrev)}, display_debug_info, &do_debug_info, TRUE },
- { { ".debug_line", ".zdebug_line", NO_ABBREVS }, display_debug_lines, &do_debug_lines, TRUE },
- { { ".debug_pubnames", ".zdebug_pubnames", NO_ABBREVS }, display_debug_pubnames, &do_debug_pubnames, FALSE },
- { { ".debug_gnu_pubnames", ".zdebug_gnu_pubnames", NO_ABBREVS }, display_debug_gnu_pubnames, &do_debug_pubnames, FALSE },
- { { ".eh_frame", "", NO_ABBREVS }, display_debug_frames, &do_debug_frames, TRUE },
- { { ".debug_macinfo", ".zdebug_macinfo", NO_ABBREVS }, display_debug_macinfo, &do_debug_macinfo, FALSE },
- { { ".debug_macro", ".zdebug_macro", NO_ABBREVS }, display_debug_macro, &do_debug_macinfo, TRUE },
- { { ".debug_str", ".zdebug_str", NO_ABBREVS }, display_debug_str, &do_debug_str, FALSE },
- { { ".debug_line_str", ".zdebug_line_str", NO_ABBREVS }, display_debug_str, &do_debug_str, FALSE },
- { { ".debug_loc", ".zdebug_loc", NO_ABBREVS }, display_debug_loc, &do_debug_loc, TRUE },
- { { ".debug_loclists", ".zdebug_loclists", NO_ABBREVS }, display_debug_loc, &do_debug_loc, TRUE },
- { { ".debug_pubtypes", ".zdebug_pubtypes", NO_ABBREVS }, display_debug_pubnames, &do_debug_pubtypes, FALSE },
- { { ".debug_gnu_pubtypes", ".zdebug_gnu_pubtypes", NO_ABBREVS }, display_debug_gnu_pubnames, &do_debug_pubtypes, FALSE },
- { { ".debug_ranges", ".zdebug_ranges", NO_ABBREVS }, display_debug_ranges, &do_debug_ranges, TRUE },
- { { ".debug_rnglists", ".zdebug_rnglists", NO_ABBREVS }, display_debug_ranges, &do_debug_ranges, TRUE },
- { { ".debug_static_func", ".zdebug_static_func", NO_ABBREVS }, display_debug_not_supported, NULL, FALSE },
- { { ".debug_static_vars", ".zdebug_static_vars", NO_ABBREVS }, display_debug_not_supported, NULL, FALSE },
- { { ".debug_types", ".zdebug_types", ABBREV (abbrev) }, display_debug_types, &do_debug_info, TRUE },
- { { ".debug_weaknames", ".zdebug_weaknames", NO_ABBREVS }, display_debug_not_supported, NULL, FALSE },
- { { ".gdb_index", "", NO_ABBREVS }, display_gdb_index, &do_gdb_index, FALSE },
- { { ".debug_names", "", NO_ABBREVS }, display_debug_names, &do_gdb_index, FALSE },
- { { ".trace_info", "", ABBREV (trace_abbrev) }, display_trace_info, &do_trace_info, TRUE },
- { { ".trace_abbrev", "", NO_ABBREVS }, display_debug_abbrev, &do_trace_abbrevs, FALSE },
- { { ".trace_aranges", "", NO_ABBREVS }, display_debug_aranges, &do_trace_aranges, FALSE },
- { { ".debug_info.dwo", ".zdebug_info.dwo", ABBREV (abbrev_dwo) }, display_debug_info, &do_debug_info, TRUE },
- { { ".debug_abbrev.dwo", ".zdebug_abbrev.dwo", NO_ABBREVS }, display_debug_abbrev, &do_debug_abbrevs, FALSE },
- { { ".debug_types.dwo", ".zdebug_types.dwo", ABBREV (abbrev_dwo) }, display_debug_types, &do_debug_info, TRUE },
- { { ".debug_line.dwo", ".zdebug_line.dwo", NO_ABBREVS }, display_debug_lines, &do_debug_lines, TRUE },
- { { ".debug_loc.dwo", ".zdebug_loc.dwo", NO_ABBREVS }, display_debug_loc, &do_debug_loc, TRUE },
- { { ".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_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 },
- { { ".gnu_debuglink", "", NO_ABBREVS }, display_debug_links, &do_debug_links, FALSE },
- { { ".gnu_debugaltlink", "", NO_ABBREVS }, display_debug_links, &do_debug_links, FALSE },
+ { { ".debug_abbrev", ".zdebug_abbrev", NO_ABBREVS }, display_debug_abbrev, &do_debug_abbrevs, false },
+ { { ".debug_aranges", ".zdebug_aranges", NO_ABBREVS }, display_debug_aranges, &do_debug_aranges, true },
+ { { ".debug_frame", ".zdebug_frame", NO_ABBREVS }, display_debug_frames, &do_debug_frames, true },
+ { { ".debug_info", ".zdebug_info", ABBREV (abbrev)}, display_debug_info, &do_debug_info, true },
+ { { ".debug_line", ".zdebug_line", NO_ABBREVS }, display_debug_lines, &do_debug_lines, true },
+ { { ".debug_pubnames", ".zdebug_pubnames", NO_ABBREVS }, display_debug_pubnames, &do_debug_pubnames, false },
+ { { ".debug_gnu_pubnames", ".zdebug_gnu_pubnames", NO_ABBREVS }, display_debug_gnu_pubnames, &do_debug_pubnames, false },
+ { { ".eh_frame", "", NO_ABBREVS }, display_debug_frames, &do_debug_frames, true },
+ { { ".debug_macinfo", ".zdebug_macinfo", NO_ABBREVS }, display_debug_macinfo, &do_debug_macinfo, false },
+ { { ".debug_macro", ".zdebug_macro", NO_ABBREVS }, display_debug_macro, &do_debug_macinfo, true },
+ { { ".debug_str", ".zdebug_str", NO_ABBREVS }, display_debug_str, &do_debug_str, false },
+ { { ".debug_line_str", ".zdebug_line_str", NO_ABBREVS }, display_debug_str, &do_debug_str, false },
+ { { ".debug_loc", ".zdebug_loc", NO_ABBREVS }, display_debug_loc, &do_debug_loc, true },
+ { { ".debug_loclists", ".zdebug_loclists", NO_ABBREVS }, display_debug_loc, &do_debug_loc, true },
+ { { ".debug_pubtypes", ".zdebug_pubtypes", NO_ABBREVS }, display_debug_pubnames, &do_debug_pubtypes, false },
+ { { ".debug_gnu_pubtypes", ".zdebug_gnu_pubtypes", NO_ABBREVS }, display_debug_gnu_pubnames, &do_debug_pubtypes, false },
+ { { ".debug_ranges", ".zdebug_ranges", NO_ABBREVS }, display_debug_ranges, &do_debug_ranges, true },
+ { { ".debug_rnglists", ".zdebug_rnglists", NO_ABBREVS }, display_debug_ranges, &do_debug_ranges, true },
+ { { ".debug_static_func", ".zdebug_static_func", NO_ABBREVS }, display_debug_not_supported, NULL, false },
+ { { ".debug_static_vars", ".zdebug_static_vars", NO_ABBREVS }, display_debug_not_supported, NULL, false },
+ { { ".debug_types", ".zdebug_types", ABBREV (abbrev) }, display_debug_types, &do_debug_info, true },
+ { { ".debug_weaknames", ".zdebug_weaknames", NO_ABBREVS }, display_debug_not_supported, NULL, false },
+ { { ".gdb_index", "", NO_ABBREVS }, display_gdb_index, &do_gdb_index, false },
+ { { ".debug_names", "", NO_ABBREVS }, display_debug_names, &do_gdb_index, false },
+ { { ".trace_info", "", ABBREV (trace_abbrev) }, display_trace_info, &do_trace_info, true },
+ { { ".trace_abbrev", "", NO_ABBREVS }, display_debug_abbrev, &do_trace_abbrevs, false },
+ { { ".trace_aranges", "", NO_ABBREVS }, display_debug_aranges, &do_trace_aranges, false },
+ { { ".debug_info.dwo", ".zdebug_info.dwo", ABBREV (abbrev_dwo) }, display_debug_info, &do_debug_info, true },
+ { { ".debug_abbrev.dwo", ".zdebug_abbrev.dwo", NO_ABBREVS }, display_debug_abbrev, &do_debug_abbrevs, false },
+ { { ".debug_types.dwo", ".zdebug_types.dwo", ABBREV (abbrev_dwo) }, display_debug_types, &do_debug_info, true },
+ { { ".debug_line.dwo", ".zdebug_line.dwo", NO_ABBREVS }, display_debug_lines, &do_debug_lines, true },
+ { { ".debug_loc.dwo", ".zdebug_loc.dwo", NO_ABBREVS }, display_debug_loc, &do_debug_loc, true },
+ { { ".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, &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 },
+ { { ".gnu_debuglink", "", NO_ABBREVS }, display_debug_links, &do_debug_links, false },
+ { { ".gnu_debugaltlink", "", NO_ABBREVS }, display_debug_links, &do_debug_links, false },
+ { { ".debug_sup", "", NO_ABBREVS }, display_debug_sup, &do_debug_links, false },
/* Separate debug info files can containt their own .debug_str section,
and this might be in *addition* to a .debug_str section already present
in the main file. Hence we need to have two entries for .debug_str. */
- { { ".debug_str", ".zdebug_str", NO_ABBREVS }, display_debug_str, &do_debug_str, FALSE },
+ { { ".debug_str", ".zdebug_str", NO_ABBREVS }, display_debug_str, &do_debug_str, false },
};
/* A static assertion. */