Merged update from upstream sources

This is an automated DistroBaker update from upstream sources.
If you do not know what this is about or would like to opt out,
contact the OSCI team.

Source: https://src.fedoraproject.org/rpms/binutils.git#45e67f9ccb533ae5a3956fa6033cc80c64dbc617
This commit is contained in:
DistroBaker 2020-10-27 19:11:41 +01:00 committed by Petr Šabata
parent ef0eaed6b5
commit 7a51afe32a
3 changed files with 1075 additions and 17 deletions

View File

@ -0,0 +1,931 @@
--- binutils.orig/binutils/dwarf.c 2020-10-21 14:15:47.101351869 +0100
+++ binutils-2.35.1/binutils/dwarf.c 2020-10-21 14:17:44.608585923 +0100
@@ -1868,7 +1868,7 @@ skip_attr_bytes (unsigned long
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;
@@ -1920,6 +1920,7 @@ skip_attr_bytes (unsigned long
case DW_FORM_ref8:
case DW_FORM_data8:
+ case DW_FORM_ref_sig8:
data += 8;
break;
@@ -1934,6 +1935,7 @@ skip_attr_bytes (unsigned long
case DW_FORM_block:
case DW_FORM_exprloc:
READ_ULEB (uvalue, data, end);
+ data += uvalue;
break;
case DW_FORM_block1:
@@ -1951,12 +1953,12 @@ skip_attr_bytes (unsigned long
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;
}
@@ -1978,7 +1980,7 @@ get_type_signedness (unsigned char *
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;
@@ -1997,6 +1999,14 @@ get_type_signedness (unsigned char *
/* 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)
@@ -2019,16 +2029,12 @@ get_type_signedness (unsigned char *
#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);
+ /* We cannot correctly process DW_FORM_ref_addr at the moment. */
+ if (attr->form != DW_FORM_ref_addr)
+ get_type_signedness (start, start + uvalue, end, pointer_size,
+ offset_size, dwarf_version, is_signed, nesting + 1);
break;
case DW_AT_encoding:
@@ -2206,7 +2212,6 @@ read_and_display_attr_value (unsigned lo
SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
else
error (_("Internal error: DWARF version is not 2, 3 or 4.\n"));
-
break;
case DW_FORM_addr:
@@ -2246,8 +2251,8 @@ read_and_display_attr_value (unsigned lo
uvalue = svalue;
break;
- case DW_FORM_GNU_str_index:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_str_index:
case DW_FORM_udata:
case DW_FORM_GNU_addr_index:
READ_ULEB (uvalue, data, end);
@@ -2663,8 +2668,10 @@ read_and_display_attr_value (unsigned lo
{
bfd_boolean is_signed = FALSE;
- get_type_signedness (start, start + uvalue, end, pointer_size,
- offset_size, dwarf_version, & is_signed, FALSE);
+ /* We cannot correctly process DW_FORM_ref_addr at the moment. */
+ if (form != DW_FORM_ref_addr)
+ get_type_signedness (start, start + uvalue, end, pointer_size,
+ offset_size, dwarf_version, & is_signed, 0);
level_type_signed[level] = is_signed;
}
break;
diff -rup binutils.orig/binutils/dwarf.c binutils-2.35.1/binutils/dwarf.c
--- binutils.orig/binutils/dwarf.c 2020-10-27 16:24:29.489636820 +0000
+++ binutils-2.35.1/binutils/dwarf.c 2020-10-27 16:24:44.507568083 +0000
@@ -849,101 +849,204 @@ fetch_indexed_value (dwarf_vma offset, d
/* 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_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;
- free (attr);
- attr = next_attr;
+ for (attr = abbrv->first_attr; attr;)
+ {
+ abbrev_attr *next_attr = attr->next;
+
+ 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_offset)
+{
+ abbrev_list * list = (abbrev_list *) xcalloc (sizeof * list, 1);
+
+ 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_offset)
+{
+ abbrev_list * list;
+
+ for (list = abbrev_lists; list != NULL; list = list->next)
+ if (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.
@@ -952,11 +1055,10 @@ add_abbrev_attr (unsigned long attribute
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;
@@ -966,7 +1068,7 @@ process_abbrev_section (unsigned char *s
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)
@@ -980,7 +1082,7 @@ process_abbrev_section (unsigned char *s
children = *start++;
- add_abbrev (entry, tag, children);
+ add_abbrev (entry, tag, children, list);
do
{
@@ -1003,7 +1105,7 @@ process_abbrev_section (unsigned char *s
break;
}
- add_abbrev_attr (attribute, form, implicit_const);
+ add_abbrev_attr (attribute, form, implicit_const, list);
}
while (attribute != 0);
}
@@ -1969,36 +2071,123 @@ skip_attr_bytes (unsigned long
return data;
}
-/* Return IS_SIGNED set to TRUE if the type at
- DATA can be determined to be a signed type. */
+/* Given form FORM with value UVALUE, locate and return the abbreviation
+ associated with it. */
+
+static abbrev_entry *
+get_type_abbrev_from_form (unsigned long form,
+ unsigned long uvalue,
+ dwarf_vma cu_offset,
+ const struct dwarf_section * section,
+ unsigned long * abbrev_num_return,
+ unsigned char ** data_return,
+ unsigned long * cu_offset_return)
+{
+ unsigned long abbrev_number;
+ abbrev_map * map;
+ abbrev_entry * entry;
+ unsigned char * data;
+
+ if (abbrev_num_return != NULL)
+ * abbrev_num_return = 0;
+ if (data_return != NULL)
+ * data_return = NULL;
+
+ switch (form)
+ {
+ case DW_FORM_GNU_ref_alt:
+ /* FIXME: We are unable to handle this form at the moment. */
+ return NULL;
+
+ case DW_FORM_ref_addr:
+ if (uvalue >= section->size)
+ {
+ warn (_("Unable to resolve ref_addr form: uvalue %lx > section size %lx (%s)\n"),
+ uvalue, (long) section->size, section->name);
+ return NULL;
+ }
+ break;
+
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref_udata:
+ if (uvalue + cu_offset > section->size)
+ {
+ warn (_("Unable to resolve ref form: uvalue %lx + cu_offset %lx > section size %lx\n"),
+ uvalue, (long) cu_offset, (long) section->size);
+ return NULL;
+ }
+ uvalue += cu_offset;
+ break;
+
+ /* FIXME: Are there other DW_FORMs that can be used by types ? */
+
+ default:
+ warn (_("Unexpected form %lx encountered whilst finding abbreviation for type\n"), form);
+ return NULL;
+ }
+
+ data = (unsigned char *) section->start + uvalue;
+ map = find_abbrev_map_by_offset (uvalue);
+
+ if (map == NULL)
+ {
+ warn (_("Unable to find abbreviations for CU offset %#lx\n"), uvalue);
+ return NULL;
+ }
+ if (map->list == NULL)
+ {
+ warn (_("Empty abbreviation list encountered for CU offset %lx\n"), uvalue);
+ return NULL;
+ }
+
+ if (cu_offset_return != NULL)
+ {
+ if (form == DW_FORM_ref_addr)
+ * cu_offset_return = map->start;
+ else
+ * cu_offset_return = cu_offset;
+ }
+
+ READ_ULEB (abbrev_number, data, section->start + section->size);
+
+ for (entry = map->list->first_abbrev; entry != NULL; entry = entry->next)
+ if (entry->number == abbrev_number)
+ break;
+
+ if (abbrev_num_return != NULL)
+ * abbrev_num_return = abbrev_number;
+
+ if (data_return != NULL)
+ * data_return = data;
+
+ if (entry == NULL)
+ warn (_("Unable to find entry for abbreviation %lu\n"), abbrev_number);
+
+ return entry;
+}
+
+/* Return IS_SIGNED set to TRUE if the type using abbreviation ENTRY
+ can be determined to be a signed type. The data for ENTRY can be
+ found starting at DATA. */
static void
-get_type_signedness (unsigned char * start,
+get_type_signedness (abbrev_entry * entry,
+ const struct dwarf_section * section,
unsigned char * data,
unsigned const char * end,
+ dwarf_vma cu_offset,
dwarf_vma pointer_size,
dwarf_vma offset_size,
int dwarf_version,
bfd_boolean * is_signed,
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)
{
@@ -2011,6 +2200,7 @@ get_type_signedness (unsigned char *
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,
@@ -2020,21 +2210,38 @@ get_type_signedness (unsigned char *
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 (uvalue >= (size_t) (end - start))
- return;
- /* We cannot correctly process DW_FORM_ref_addr at the moment. */
- if (attr->form != DW_FORM_ref_addr)
- get_type_signedness (start, start + uvalue, end, pointer_size,
- offset_size, dwarf_version, is_signed, nesting + 1);
+ {
+ 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:
@@ -2276,12 +2483,12 @@ read_and_display_attr_value (unsigned lo
{
case DW_FORM_ref_addr:
if (!do_loc)
- printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x",uvalue));
+ printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue));
break;
case DW_FORM_GNU_ref_alt:
if (!do_loc)
- printf ("%c<alt 0x%s>", delimiter, dwarf_vmatoa ("x",uvalue));
+ printf ("%c<alt 0x%s>", delimiter, dwarf_vmatoa ("x", uvalue));
/* FIXME: Follow the reference... */
break;
@@ -2667,11 +2874,18 @@ read_and_display_attr_value (unsigned lo
&& uvalue < (size_t) (end - start))
{
bfd_boolean is_signed = FALSE;
-
- /* We cannot correctly process DW_FORM_ref_addr at the moment. */
- if (form != DW_FORM_ref_addr)
- get_type_signedness (start, start + uvalue, end, pointer_size,
- offset_size, dwarf_version, & is_signed, 0);
+ abbrev_entry * type_abbrev;
+ unsigned char * type_data;
+ unsigned long type_cu_offset;
+
+ type_abbrev = get_type_abbrev_from_form (form, uvalue, cu_offset,
+ section, NULL, & type_data, & type_cu_offset);
+ if (type_abbrev != NULL)
+ {
+ get_type_signedness (type_abbrev, section, type_data, end, type_cu_offset,
+ pointer_size, offset_size, dwarf_version,
+ & is_signed, 0);
+ }
level_type_signed[level] = is_signed;
}
break;
@@ -2993,40 +3207,22 @@ read_and_display_attr_value (unsigned lo
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 ("]");
}
}
@@ -3245,8 +3441,98 @@ process_debug_info (struct dwarf_section
if (!do_loc && dwarf_start_die == 0)
introduce (section, FALSE);
+
+ free_all_abbrevs ();
+ free (cu_abbrev_map);
+ cu_abbrev_map = NULL;
+ next_free_abbrev_map_entry = 0;
- for (section_begin = start, unit = 0; start < end; unit++)
+ /* In order to be able to resolve DW_FORM_ref_attr forms we need
+ to load *all* of the abbrevs for all CUs in this .debug_info
+ section. This does effectively mean that we (partially) read
+ every CU header twice. */
+ for (section_begin = start; start < end;)
+ {
+ DWARF2_Internal_CompUnit compunit;
+ unsigned char * hdrptr;
+ dwarf_vma 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);
+
+ list = find_abbrev_list_by_abbrev_offset (compunit.cu_abbrev_offset);
+ if (list == NULL)
+ {
+ dwarf_vma abbrev_base;
+ size_t abbrev_size;
+ unsigned char * next;
+
+ 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 = new_abbrev_list (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;
@@ -3262,6 +3548,7 @@ process_debug_info (struct dwarf_section
struct cu_tu_set *this_set;
dwarf_vma abbrev_base;
size_t abbrev_size;
+ abbrev_list * list = NULL;
hdrptr = start;
@@ -3434,8 +3721,6 @@ process_debug_info (struct dwarf_section
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"),
@@ -3448,11 +3733,22 @@ process_debug_info (struct dwarf_section
(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 (compunit.cu_abbrev_offset);
+ if (list == NULL)
+ {
+ unsigned char * next;
+
+ list = new_abbrev_list (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;
@@ -3532,11 +3828,13 @@ process_debug_info (struct dwarf_section
/* 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)
@@ -5721,30 +6019,37 @@ display_debug_abbrev (struct dwarf_secti
{
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 (offset);
+ if (list == NULL)
+ {
+ list = new_abbrev_list (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"));
@@ -10776,8 +11081,12 @@ 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);
Only in binutils-2.35.1/binutils: dwarf.c.orig

View File

@ -0,0 +1,109 @@
--- binutils.orig/binutils/dwarf.c 2020-10-15 12:13:21.960799738 +0100
+++ binutils-2.35.1/binutils/dwarf.c 2020-10-15 13:02:39.454692627 +0100
@@ -10427,7 +10427,7 @@ load_separate_debug_info (const char *
{
warn (_("Corrupt debuglink section: %s\n"),
xlink->name ? xlink->name : xlink->uncompressed_name);
- return FALSE;
+ return NULL;
}
/* Attempt to locate the separate file.
@@ -10587,7 +10587,7 @@ load_separate_debug_info (const char *
{
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
@@ -10632,6 +10632,52 @@ load_dwo_file (const char * main_filenam
return separate_handle;
}
+/* Load a debuglink section and/or a debugaltlink section, if either are present.
+ Recursively check the loaded files for more of these sections.
+ FIXME: Should also check for DWO_* entries in the newlu loaded files. */
+
+static void
+check_for_and_load_links (void * file, const char * filename)
+{
+ void * handle = NULL;
+
+ if (load_debug_section (gnu_debugaltlink, file))
+ {
+ Build_id_data build_id_data;
+
+ handle = load_separate_debug_info (filename,
+ & debug_displays[gnu_debugaltlink].section,
+ parse_gnu_debugaltlink,
+ check_gnu_debugaltlink,
+ & build_id_data,
+ file);
+ if (handle)
+ {
+ assert (handle == first_separate_info->handle);
+ check_for_and_load_links (first_separate_info->handle,
+ first_separate_info->filename);
+ }
+ }
+
+ if (load_debug_section (gnu_debuglink, file))
+ {
+ unsigned long crc32;
+
+ handle = load_separate_debug_info (filename,
+ & debug_displays[gnu_debuglink].section,
+ parse_gnu_debuglink,
+ check_gnu_debuglink,
+ & crc32,
+ file);
+ if (handle)
+ {
+ assert (handle == first_separate_info->handle);
+ check_for_and_load_links (first_separate_info->handle,
+ first_separate_info->filename);
+ }
+ }
+}
+
/* Load the separate debug info file(s) attached to FILE, if any exist.
Returns TRUE if any were found, FALSE otherwise.
If TRUE is returned then the linked list starting at first_separate_info
@@ -10707,34 +10753,10 @@ load_separate_debug_files (void * file,
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,
- file);
- }
-
- 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,
- file);
- }
-
+ check_for_and_load_links (file, filename);
if (first_separate_info != NULL)
return TRUE;

View File

@ -2,7 +2,7 @@
Summary: A GNU collection of binary utilities
Name: %{?cross}binutils%{?_with_debug:-debug}
Version: 2.35.1
Release: 5%{?dist}
Release: 8%{?dist}
License: GPLv3+
URL: https://sourceware.org/binutils
@ -186,69 +186,78 @@ Patch10: binutils-attach-to-group.patch
# Purpose: Allow OS specific sections in section groups.
# Lifetime: Fixed in 2.36 (maybe)
Patch12: binutils-special-sections-in-groups.patch
Patch11: binutils-special-sections-in-groups.patch
# Purpose: Fix linker testsuite failures.
# Lifetime: Fixed in 2.36 (maybe)
Patch13: binutils-fix-testsuite-failures.patch
Patch12: binutils-fix-testsuite-failures.patch
# Purpose: Stop gold from aborting when input sections with the same name
# have different flags.
# Lifetime: Fixed in 2.36 (maybe)
Patch14: binutils-gold-mismatched-section-flags.patch
Patch13: binutils-gold-mismatched-section-flags.patch
# Purpose: Add a check to the GOLD linker for a corrupt input file
# with a fuzzed section offset.
# Lifetime: Fixed in 2.36 (maybe)
Patch15: binutils-CVE-2019-1010204.patch
Patch14: binutils-CVE-2019-1010204.patch
# Purpose: Change the gold configuration script to only warn about
# unsupported targets. This allows the binutils to be built with
# BPF support enabled.
# Lifetime: Permanent.
Patch17: binutils-gold-warn-unsupported.patch
Patch15: binutils-gold-warn-unsupported.patch
# Purpose: Fix compile time warning messages building s390 target with gcc-10.
# Lifetime: Should be fixed in 2.36.
Patch19: binutils-s390-build.patch
Patch16: binutils-s390-build.patch
# Purpose: Fix LTO problems running config mini-builds.
# Lifetime: Should be fixed in 2.36.
Patch20: binutils-config.patch
Patch17: binutils-config.patch
# Purpose: Fix compile time warning messages building with gcc-10.
# Lifetime: Should be fixed in 2.36.
Patch21: binutils-warnings.patch
Patch18: binutils-warnings.patch
# Purpose: Fix compile time warning messages building with gcc-10. (part 2).
# Lifetime: Should be fixed in 2.36.
Patch22: binutils-gcc-10-fixes.patch
Patch19: binutils-gcc-10-fixes.patch
# Purpose: Fixes for linking LTO objects.
# Lifetime: Fixed in 2.36
Patch23: binutils-add-sym-cache-to-elf-link-hash.patch
Patch24: binutils-elf-add-objects.patch
Patch20: binutils-add-sym-cache-to-elf-link-hash.patch
Patch21: binutils-elf-add-objects.patch
# Purpose: Fix handling of relocations for AArch64 conditional branches.
# Lifetime: Fixed in 2.36
Patch25: binutils-aarch64-condbranch-relocs.patch
Patch22: binutils-aarch64-condbranch-relocs.patch
# Purpose: Fix the PowerPC disassembler so that it ignores annobin symbols.
# Lifetime: Fixed in 2.36
Patch26: binutils-ppc-annobin-disassembly.patch
Patch23: binutils-ppc-annobin-disassembly.patch
# Purpose: Fix the strip program to cope when merging multiple same-named
# sections.
# Lifetime: Fixed in 2.36
Patch27: binutils-strip-merge.patch
Patch24: binutils-strip-merge.patch
# Purpose: Fix various problems with the PowerPC arch10 extensions.
# Lifetime: Fixed in 2.36
Patch28: binutils-Power10-fixes.patch
Patch25: binutils-Power10-fixes.patch
# Purpose: Allow plugin syms to mark as-needed shared libs needed.
# Lifetime: Fixed in 2.36
Patch29: binutils-plugin-as-needed.patch
Patch26: binutils-plugin-as-needed.patch
# Purpose: Recursively follow .gnu_debuglink and .gnu_debugaltlink sections.
# Lifetime: Fixed in 2.36
Patch27: binutils-recursive-debuglink-following.patch
# Purpose: Fix the DWARF parser to skip DW_FORM_ref_addr types
# when attempting to determine a type's signedness.
# Lifetime: Fixed in 2.36
Patch28: binutils-dwarf-type-sign.patch
#----------------------------------------------------------------------------
@ -823,6 +832,15 @@ exit 0
#----------------------------------------------------------------------------
%changelog
* Tue Oct 27 2020 Nick Clifton <nickc@redhat.com> - 2.35.1-8
- Really fix erroneous decoding of LEB128 values. (#1891171)
* Wed Oct 21 2020 Nick Clifton <nickc@redhat.com> - 2.35.1-7
- Fix erroneous decoding of LEB128 values. (#188716)
* Thu Oct 15 2020 Nick Clifton <nickc@redhat.com> - 2.35.1-6
- Make readelf and objdump recursively follow debug links. (PR 26595)
* Fri Oct 09 2020 Nick Clifton <nickc@redhat.com> - 2.35.1-5
- Allow plugin syms to mark as-needed shared libs needed