ret = (const unsigned char *)
_("<no NUL byte at end of .debug_str section>");
- return ret;
+ return ret;
}
static const unsigned char *
}
index_offset = idx * offset_size;
-
+
if (this_set != NULL)
index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS];
/* FIXME: There are better and more efficient ways to handle
these structures. For now though, I just want something that
is simple to implement. */
+/* Records a single attribute in an abbrev. */
typedef struct abbrev_attr
{
- unsigned long attribute;
- unsigned long form;
- bfd_signed_vma implicit_const;
- struct abbrev_attr *next;
+ unsigned long attribute;
+ unsigned long form;
+ bfd_signed_vma implicit_const;
+ struct abbrev_attr * next;
}
abbrev_attr;
+/* Records a single abbrev. */
typedef struct abbrev_entry
{
- unsigned long entry;
- unsigned long tag;
- int children;
- struct abbrev_attr *first_attr;
- struct abbrev_attr *last_attr;
- struct abbrev_entry *next;
+ unsigned long number;
+ unsigned long tag;
+ int children;
+ struct abbrev_attr * first_attr;
+ struct abbrev_attr * last_attr;
+ struct abbrev_entry * next;
}
abbrev_entry;
-static abbrev_entry *first_abbrev = NULL;
-static abbrev_entry *last_abbrev = NULL;
+/* Records a set of abbreviations. */
+typedef struct abbrev_list
+{
+ abbrev_entry * first_abbrev;
+ abbrev_entry * last_abbrev;
+ dwarf_vma abbrev_base;
+ dwarf_vma abbrev_offset;
+ struct abbrev_list * next;
+ unsigned char * start_of_next_abbrevs;
+}
+abbrev_list;
+
+/* Records all the abbrevs found so far. */
+static struct abbrev_list * abbrev_lists = NULL;
+
+typedef struct abbrev_map
+{
+ dwarf_vma start;
+ dwarf_vma end;
+ abbrev_list * list;
+} abbrev_map;
+
+/* Maps between CU offsets and abbrev sets. */
+static abbrev_map * cu_abbrev_map = NULL;
+static unsigned long num_abbrev_map_entries = 0;
+static unsigned long next_free_abbrev_map_entry = 0;
+
+#define INITIAL_NUM_ABBREV_MAP_ENTRIES 8
+#define ABBREV_MAP_ENTRIES_INCREMENT 8
static void
-free_abbrevs (void)
+record_abbrev_list_for_cu (dwarf_vma start, dwarf_vma end, abbrev_list * list)
{
- abbrev_entry *abbrv;
+ if (cu_abbrev_map == NULL)
+ {
+ num_abbrev_map_entries = INITIAL_NUM_ABBREV_MAP_ENTRIES;
+ cu_abbrev_map = xmalloc (num_abbrev_map_entries * sizeof (* cu_abbrev_map));
+ }
+ else if (next_free_abbrev_map_entry == num_abbrev_map_entries)
+ {
+ num_abbrev_map_entries += ABBREV_MAP_ENTRIES_INCREMENT;
+ cu_abbrev_map = xrealloc (cu_abbrev_map, num_abbrev_map_entries * sizeof (* cu_abbrev_map));
+ }
- for (abbrv = first_abbrev; abbrv;)
+ 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_all_abbrevs (void)
+{
+ abbrev_list * list;
+
+ for (list = abbrev_lists; list != NULL;)
{
- abbrev_entry *next_abbrev = abbrv->next;
- abbrev_attr *attr;
+ abbrev_list * next = list->next;
+ abbrev_entry * abbrv;
- for (attr = abbrv->first_attr; attr;)
+ for (abbrv = list->first_abbrev; abbrv != NULL;)
{
- abbrev_attr *next_attr = attr->next;
+ abbrev_entry * next_abbrev = abbrv->next;
+ abbrev_attr * attr;
+
+ for (attr = abbrv->first_attr; attr;)
+ {
+ abbrev_attr *next_attr = attr->next;
+
+ free (attr);
+ attr = next_attr;
+ }
- free (attr);
- attr = next_attr;
+ free (abbrv);
+ abbrv = next_abbrev;
}
- free (abbrv);
- abbrv = next_abbrev;
+ free (list);
+ list = next;
}
- last_abbrev = first_abbrev = NULL;
+ abbrev_lists = NULL;
+}
+
+static abbrev_list *
+new_abbrev_list (dwarf_vma abbrev_base, dwarf_vma abbrev_offset)
+{
+ abbrev_list * list = (abbrev_list *) xcalloc (sizeof * list, 1);
+
+ list->abbrev_base = abbrev_base;
+ list->abbrev_offset = abbrev_offset;
+
+ list->next = abbrev_lists;
+ abbrev_lists = list;
+
+ return list;
+}
+
+static abbrev_list *
+find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base,
+ dwarf_vma abbrev_offset)
+{
+ abbrev_list * list;
+
+ for (list = abbrev_lists; list != NULL; list = list->next)
+ if (list->abbrev_base == abbrev_base
+ && list->abbrev_offset == abbrev_offset)
+ return list;
+
+ return NULL;
+}
+
+/* Find the abbreviation map for the CU that includes OFFSET.
+ OFFSET is an absolute offset from the start of the .debug_info section. */
+/* FIXME: This function is going to slow down readelf & objdump.
+ Consider using a better algorithm to mitigate this effect. */
+
+static abbrev_map *
+find_abbrev_map_by_offset (dwarf_vma offset)
+{
+ unsigned long i;
+
+ for (i = 0; i < next_free_abbrev_map_entry; i++)
+ if (cu_abbrev_map[i].start <= offset
+ && cu_abbrev_map[i].end > offset)
+ return cu_abbrev_map + i;
+
+ return NULL;
}
static void
-add_abbrev (unsigned long number, unsigned long tag, int children)
+add_abbrev (unsigned long number,
+ unsigned long tag,
+ int children,
+ abbrev_list * list)
{
- abbrev_entry *entry;
+ abbrev_entry * entry;
- entry = (abbrev_entry *) malloc (sizeof (*entry));
- if (entry == NULL)
- /* ugg */
- return;
+ entry = (abbrev_entry *) xmalloc (sizeof (*entry));
- entry->entry = number;
+ entry->number = number;
entry->tag = tag;
entry->children = children;
entry->first_attr = NULL;
entry->last_attr = NULL;
entry->next = NULL;
- if (first_abbrev == NULL)
- first_abbrev = entry;
+ assert (list != NULL);
+
+ if (list->first_abbrev == NULL)
+ list->first_abbrev = entry;
else
- last_abbrev->next = entry;
+ list->last_abbrev->next = entry;
- last_abbrev = entry;
+ list->last_abbrev = entry;
}
static void
-add_abbrev_attr (unsigned long attribute, unsigned long form,
- bfd_signed_vma implicit_const)
+add_abbrev_attr (unsigned long attribute,
+ unsigned long form,
+ bfd_signed_vma implicit_const,
+ abbrev_list * list)
{
abbrev_attr *attr;
- attr = (abbrev_attr *) malloc (sizeof (*attr));
- if (attr == NULL)
- /* ugg */
- return;
+ attr = (abbrev_attr *) xmalloc (sizeof (*attr));
attr->attribute = attribute;
attr->form = form;
attr->implicit_const = implicit_const;
attr->next = NULL;
- if (last_abbrev->first_attr == NULL)
- last_abbrev->first_attr = attr;
+ assert (list != NULL && list->last_abbrev != NULL);
+
+ if (list->last_abbrev->first_attr == NULL)
+ list->last_abbrev->first_attr = attr;
else
- last_abbrev->last_attr->next = attr;
+ list->last_abbrev->last_attr->next = attr;
- last_abbrev->last_attr = attr;
+ list->last_abbrev->last_attr = attr;
}
/* Processes the (partial) contents of a .debug_abbrev section.
an abbreviation set was found. */
static unsigned char *
-process_abbrev_section (unsigned char *start, unsigned char *end)
+process_abbrev_set (unsigned char * start,
+ const unsigned char * end,
+ abbrev_list * list)
{
- if (first_abbrev != NULL)
- return NULL;
-
while (start < end)
{
unsigned 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>");
case DW_FORM_ref_addr:
if (dwarf_version == 2)
SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
- else if (dwarf_version == 3 || dwarf_version == 4)
+ else if (dwarf_version > 2)
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
else
return NULL;
break;
case DW_FORM_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 abbrev_entry *
+get_type_abbrev_from_form (unsigned long form,
+ unsigned long uvalue,
+ dwarf_vma cu_offset,
+ const struct dwarf_section * section,
+ unsigned long * abbrev_num_return,
+ unsigned char ** data_return,
+ unsigned long * cu_offset_return)
+{
+ unsigned long abbrev_number;
+ abbrev_map * map;
+ abbrev_entry * entry;
+ unsigned char * data;
+
+ if (abbrev_num_return != NULL)
+ * abbrev_num_return = 0;
+ if (data_return != NULL)
+ * data_return = NULL;
+
+ switch (form)
+ {
+ case DW_FORM_GNU_ref_alt:
+ /* FIXME: We are unable to handle this form at the moment. */
+ return NULL;
+
+ case DW_FORM_ref_addr:
+ if (uvalue >= section->size)
+ {
+ warn (_("Unable to resolve ref_addr form: uvalue %lx > section size %lx (%s)\n"),
+ uvalue, (long) section->size, section->name);
+ return NULL;
+ }
+ break;
+
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_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)
+ warn (_("Unable to find entry for abbreviation %lu\n"), abbrev_number);
+
+ return entry;
+}
+
+/* Return IS_SIGNED set to TRUE if the type using abbreviation ENTRY
+ can be determined to be a signed type. The data for ENTRY can be
+ found starting at DATA. */
static void
-get_type_signedness (unsigned char * start,
+get_type_signedness (abbrev_entry * entry,
+ const struct dwarf_section * section,
unsigned char * data,
unsigned const char * end,
+ dwarf_vma cu_offset,
dwarf_vma pointer_size,
dwarf_vma offset_size,
int dwarf_version,
bfd_boolean * is_signed,
- bfd_boolean is_nested)
+ unsigned int nesting)
{
- unsigned long abbrev_number;
- abbrev_entry * entry;
abbrev_attr * attr;
* is_signed = FALSE;
- READ_ULEB (abbrev_number, data, end);
-
- for (entry = first_abbrev;
- entry != NULL && entry->entry != abbrev_number;
- entry = entry->next)
- continue;
-
- if (entry == NULL)
- /* FIXME: Issue a warning ? */
- return;
+#define MAX_NESTING 20
+ if (nesting > MAX_NESTING)
+ {
+ /* FIXME: Warn - or is this expected ?
+ NB/ We need to avoid infinite recursion. */
+ return;
+ }
for (attr = entry->first_attr;
attr != NULL && attr->attribute;
attr = attr->next)
{
+ unsigned char * orig_data = data;
dwarf_vma uvalue = 0;
data = skip_attr_bytes (attr->form, data, end, pointer_size,
switch (attr->attribute)
{
-#if 0 /* FIXME: It would be nice to print the name of the type,
- but this would mean updating a lot of binutils tests. */
+ case DW_AT_linkage_name:
case DW_AT_name:
- if (attr->form == DW_FORM_strp)
- printf ("%s", fetch_indirect_string (uvalue));
+ if (do_wide)
+ {
+ if (attr->form == DW_FORM_strp)
+ printf (", %s", fetch_indirect_string (uvalue));
+ else if (attr->form == DW_FORM_string)
+ printf (", %s", orig_data);
+ }
break;
-#endif
+
case DW_AT_type:
/* Recurse. */
- if (is_nested)
- {
- /* FIXME: Warn - or is this expected ?
- NB/ We need to avoid infinite recursion. */
- return;
- }
- if (uvalue >= (size_t) (end - start))
- return;
- get_type_signedness (start, start + uvalue, end, pointer_size,
- offset_size, dwarf_version, is_signed, TRUE);
+ {
+ abbrev_entry * type_abbrev;
+ unsigned char * type_data;
+ unsigned long type_cu_offset;
+
+ type_abbrev = get_type_abbrev_from_form (attr->form,
+ uvalue,
+ cu_offset,
+ section,
+ NULL /* abbrev num return */,
+ & type_data,
+ & type_cu_offset);
+ if (type_abbrev == NULL)
+ break;
+
+ get_type_signedness (type_abbrev, section, type_data, end, type_cu_offset,
+ pointer_size, offset_size, dwarf_version,
+ is_signed, nesting + 1);
+ }
break;
case DW_AT_encoding:
printf ("[default]");
return;
}
-
+
switch (form)
{
case DW_FORM_block:
bfd_boolean is_signed =
(level > 0 && level <= MAX_CU_NESTING)
? level_type_signed [level - 1] : FALSE;
-
+
printf ("(");
while (uvalue)
{
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:
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
else
error (_("Internal error: DW_FORM_ref_addr is not supported in DWARF version 1.\n"));
-
break;
case DW_FORM_addr:
{
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_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:
const char * suffix = strrchr (section->name, '.');
bfd_boolean dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? TRUE : FALSE;
- 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:
if (!do_loc)
- printf (_("%c(addr_index: 0x%s): %s"), delimiter,
- dwarf_vmatoa ("x", uvalue),
- fetch_indexed_value (uvalue * pointer_size, 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 (uvalue * pointer_size, pointer_size));
+ else
+ printf (_("%c(addr_index: 0x%s): %s"), delimiter,
+ dwarf_vmatoa ("x", uvalue),
+ fetch_indexed_value (uvalue * pointer_size, pointer_size));
+ }
break;
default:
break;
}
break;
-
+
case DW_AT_comp_dir:
/* FIXME: Also extract a build-id in a CU/TU. */
if (need_dwo_info)
break;
}
break;
-
+
case DW_AT_GNU_dwo_id:
if (need_dwo_info)
switch (form)
break;
}
break;
-
+
default:
break;
}
&& uvalue < (size_t) (end - start))
{
bfd_boolean 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;
-
- if (form == DW_FORM_ref1
- || form == DW_FORM_ref2
- || form == DW_FORM_ref4
- || form == DW_FORM_ref_udata)
- uvalue += cu_offset;
+ unsigned long abbrev_number;
+ abbrev_entry *entry;
- if (uvalue >= section->size)
- warn (_("Offset %s used as value for DW_AT_import attribute of DIE at offset 0x%lx is too big.\n"),
- dwarf_vmatoa ("x", uvalue),
- (unsigned long) (orig_data - section->start));
+ entry = get_type_abbrev_from_form (form, uvalue, cu_offset,
+ section, & abbrev_number, NULL, NULL);
+ if (entry == NULL)
+ {
+ if (form != DW_FORM_GNU_ref_alt)
+ warn (_("Offset %s used as value for DW_AT_import attribute of DIE at offset 0x%lx is too big.\n"),
+ dwarf_vmatoa ("x", uvalue),
+ (unsigned long) (orig_data - section->start));
+ }
else
{
- unsigned long abbrev_number;
- abbrev_entry *entry;
- 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 ("]");
}
}
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.
load_debug_section_with_follow (str_index_dwo, file);
load_debug_section_with_follow (debug_addr, file);
}
-
+
load_debug_section_with_follow (abbrev_sec, file);
if (debug_displays [abbrev_sec].section.start == NULL)
{
if (!do_loc && dwarf_start_die == 0)
introduce (section, FALSE);
-
- for (section_begin = start, unit = 0; start < end; unit++)
+
+ 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 (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;
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;
/* 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)
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"),
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;
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;
{
abbrev_entry *entry;
unsigned char *start = section->start;
- unsigned char *end = start + section->size;
+ const unsigned char *end = start + section->size;
introduce (section, FALSE);
do
{
- unsigned char *last;
-
- free_abbrevs ();
+ abbrev_list * list;
+ dwarf_vma offset;
- last = start;
- start = process_abbrev_section (start, end);
+ offset = start - section->start;
+ list = find_abbrev_list_by_abbrev_offset (0, offset);
+ if (list == NULL)
+ {
+ list = new_abbrev_list (0, offset);
+ start = process_abbrev_set (start, end, list);
+ list->start_of_next_abbrevs = start;
+ }
+ else
+ start = list->start_of_next_abbrevs;
- if (first_abbrev == NULL)
+ if (list->first_abbrev == NULL)
continue;
- printf (_(" Number TAG (0x%lx)\n"), (long) (last - section->start));
+ printf (_(" Number TAG (0x%lx)\n"), (long) offset);
- for (entry = first_abbrev; entry; entry = entry->next)
+ for (entry = list->first_abbrev; entry; entry = entry->next)
{
abbrev_attr *attr;
printf (" %ld %s [%s]\n",
- entry->entry,
+ entry->number,
get_TAG_name (entry->tag),
entry->children ? _("has children") : _("no children"));
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,
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);
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)
if (cu_tu_indexes_read == -1)
{
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;
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)
xlink->name ? xlink->name : xlink->uncompressed_name);
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;
do_follow_links = 0;
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;
for (i = 0; i < max; i++)
free_debug_section ((enum dwarf_section_display_enum) i);
free ((void *) d);
}
first_separate_info = NULL;
-
+
free_dwo_info ();
}