The last change was premature, 2.39 isn't actually affected

by the problem, it was introduced in one of the prerequisite
patches, remove all traces of the change.

OBS-URL: https://build.opensuse.org/package/show/devel:gcc/binutils?expand=0&rev=419
This commit is contained in:
Michael Matz 2022-09-01 11:57:45 +00:00 committed by Git OBS Bridge
parent 8d8118647c
commit 9460b44a5c
5 changed files with 0 additions and 990 deletions

View File

@ -1,532 +0,0 @@
From 175b91507b83ad42607d2f6dadaf55b7b511bdbe Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Wed, 20 Jul 2022 18:28:50 +0930
Subject: [PATCH] miscellaneous dwarf.c tidies
* dwarf.c: Leading and trailing whitespace fixes.
(free_abbrev_list): New function.
(free_all_abbrevs): Use the above. Free cu_abbrev_map here too.
(process_abbrev_set): Print actual section name on error.
(get_type_abbrev_from_form): Add overflow check.
(free_debug_memory): Don't free cu_abbrev_map here..
(process_debug_info): ..or here. Warn on another case of not
finding a neeeded abbrev.
---
binutils/dwarf.c | 216 +++++++++++++++++++++++------------------------
1 file changed, 106 insertions(+), 110 deletions(-)
Index: binutils-2.39/binutils/dwarf.c
===================================================================
--- binutils-2.39.orig/binutils/dwarf.c 2022-09-01 13:51:14.818699924 +0200
+++ binutils-2.39/binutils/dwarf.c 2022-09-01 13:51:32.090984628 +0200
@@ -806,7 +806,7 @@ fetch_indexed_value (dwarf_vma idx,
pointer_size = 4;
bias = 12;
}
-
+
dwarf_vma offset = idx * pointer_size;
/* Offsets are biased by the size of the section header
@@ -901,38 +901,41 @@ record_abbrev_list_for_cu (dwarf_vma sta
next_free_abbrev_map_entry ++;
}
-static void
-free_all_abbrevs (void)
+static abbrev_list *
+free_abbrev_list (abbrev_list *list)
{
- abbrev_list * list;
+ abbrev_entry *abbrv = list->first_abbrev;
- for (list = abbrev_lists; list != NULL;)
+ while (abbrv)
{
- abbrev_list * next = list->next;
- abbrev_entry * abbrv;
+ abbrev_attr *attr = abbrv->first_attr;
- for (abbrv = list->first_abbrev; abbrv != NULL;)
+ while (attr)
{
- 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 (abbrv);
- abbrv = next_abbrev;
+ abbrev_attr *next_attr = attr->next;
+ free (attr);
+ attr = next_attr;
}
- free (list);
- list = next;
+ abbrev_entry *next_abbrev = abbrv->next;
+ free (abbrv);
+ abbrv = next_abbrev;
}
- abbrev_lists = NULL;
+ abbrev_list *next = list->next;
+ free (list);
+ return next;
+}
+
+static void
+free_all_abbrevs (void)
+{
+ while (abbrev_lists)
+ abbrev_lists = free_abbrev_list (abbrev_lists);
+
+ free (cu_abbrev_map);
+ cu_abbrev_map = NULL;
+ next_free_abbrev_map_entry = 0;
}
static abbrev_list *
@@ -978,7 +981,7 @@ find_abbrev_map_by_offset (dwarf_vma off
&& cu_abbrev_map[i].end > offset)
return cu_abbrev_map + i;
- return NULL;
+ return NULL;
}
static void
@@ -1119,7 +1122,7 @@ process_abbrev_set (struct dwarf_section
}
/* Report the missing single zero which ends the section. */
- error (_(".debug_abbrev section not zero terminated\n"));
+ error (_("%s section not zero terminated\n"), section->name);
return NULL;
}
@@ -1842,7 +1845,7 @@ fetch_alt_indirect_string (dwarf_vma off
dwarf_vmatoa ("x", offset));
return _("<offset is too big>");
}
-
+
static const char *
get_AT_name (unsigned long attribute)
{
@@ -2124,7 +2127,8 @@ get_type_abbrev_from_form (unsigned long
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- if (uvalue + cu_offset > (size_t) (cu_end - section->start))
+ if (uvalue + cu_offset < uvalue
+ || uvalue + cu_offset > (size_t) (cu_end - section->start))
{
warn (_("Unable to resolve ref form: uvalue %lx + cu_offset %lx > CU size %lx\n"),
uvalue, (long) cu_offset, (long) (cu_end - section->start));
@@ -2161,7 +2165,7 @@ get_type_abbrev_from_form (unsigned long
else
*map_return = NULL;
}
-
+
READ_ULEB (abbrev_number, data, section->start + section->size);
for (entry = map->list->first_abbrev; entry != NULL; entry = entry->next)
@@ -2750,10 +2754,10 @@ read_and_display_attr_value (unsigned lo
if (form == DW_FORM_loclistx)
{
if (dwo)
- {
- index = fetch_indexed_value (uvalue, loclists_dwo, 0);
- index += (offset_size == 8) ? 20 : 12;
- }
+ {
+ index = fetch_indexed_value (uvalue, loclists_dwo, 0);
+ index += (offset_size == 8) ? 20 : 12;
+ }
else if (debug_info_p == NULL)
{
index = fetch_indexed_value (uvalue, loclists, 0);
@@ -2771,21 +2775,21 @@ read_and_display_attr_value (unsigned lo
else if (form == DW_FORM_rnglistx)
{
if (dwo)
- {
- index = fetch_indexed_value (uvalue, rnglists_dwo, 0);
- index += (offset_size == 8) ? 20 : 12;
- }
+ {
+ index = fetch_indexed_value (uvalue, rnglists_dwo, 0);
+ index += (offset_size == 8) ? 20 : 12;
+ }
else
- {
- if (debug_info_p == NULL)
- base = 0;
- else
- base = debug_info_p->rnglists_base;
- /* We do not have a cached value this time, so we perform the
- computation manually. */
- index = fetch_indexed_value (uvalue, rnglists, base);
- index += base;
- }
+ {
+ if (debug_info_p == NULL)
+ base = 0;
+ else
+ base = debug_info_p->rnglists_base;
+ /* We do not have a cached value this time, so we perform the
+ computation manually. */
+ index = fetch_indexed_value (uvalue, rnglists, base);
+ index += base;
+ }
}
else
{
@@ -2811,7 +2815,7 @@ read_and_display_attr_value (unsigned lo
if (!do_loc)
printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset));
break;
-
+
default:
warn (_("Unrecognized form: 0x%lx\n"), form);
/* What to do? Consume a byte maybe? */
@@ -2836,9 +2840,9 @@ read_and_display_attr_value (unsigned lo
case DW_AT_rnglists_base:
if (debug_info_p->rnglists_base)
warn (_("CU @ 0x%s has multiple rnglists_base values (0x%s and 0x%s)"),
- dwarf_vmatoa ("x", debug_info_p->cu_offset),
- dwarf_vmatoa ("x", debug_info_p->rnglists_base),
- dwarf_vmatoa ("x", uvalue));
+ dwarf_vmatoa ("x", debug_info_p->cu_offset),
+ dwarf_vmatoa ("x", debug_info_p->rnglists_base),
+ dwarf_vmatoa ("x", uvalue));
debug_info_p->rnglists_base = uvalue;
break;
case DW_AT_str_offsets_base:
@@ -2988,7 +2992,7 @@ read_and_display_attr_value (unsigned lo
case DW_FORM_strx3:
case DW_FORM_strx4:
add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, false,
- debug_info_p->str_offsets_base),
+ debug_info_p->str_offsets_base),
cu_offset);
break;
case DW_FORM_string:
@@ -3022,7 +3026,7 @@ read_and_display_attr_value (unsigned lo
case DW_FORM_strx3:
case DW_FORM_strx4:
add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, false,
- debug_info_p->str_offsets_base),
+ debug_info_p->str_offsets_base),
cu_offset);
break;
case DW_FORM_string:
@@ -3653,11 +3657,8 @@ process_debug_info (struct dwarf_section
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
+ /* In order to be able to resolve DW_FORM_ref_addr 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. */
@@ -4028,12 +4029,11 @@ process_debug_info (struct dwarf_section
/* Scan through the abbreviation list until we reach the
correct entry. */
- if (list == NULL)
- continue;
-
- for (entry = list->first_abbrev; entry != NULL; entry = entry->next)
- if (entry->number == abbrev_number)
- break;
+ entry = NULL;
+ if (list != NULL)
+ for (entry = list->first_abbrev; entry != NULL; entry = entry->next)
+ if (entry->number == abbrev_number)
+ break;
if (entry == NULL)
{
@@ -4057,7 +4057,7 @@ process_debug_info (struct dwarf_section
break;
case DW_TAG_compile_unit:
case DW_TAG_skeleton_unit:
- need_base_address = 1;
+ need_base_address = 1;
need_dwo_info = do_loc;
break;
case DW_TAG_entry_point:
@@ -4440,7 +4440,7 @@ display_debug_sup (struct dwarf_section
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"));
+ warn (_("corrupt .debug_sup section: is_supplementary not 0 or 1\n"));
sup_filename = start;
if (is_supplementary && sup_filename[0] != 0)
@@ -5619,7 +5619,7 @@ display_debug_lines_decoded (struct dwar
printf ("%s %11d %#18" DWARF_VMA_FMT "x",
newFileName, state_machine_regs.line,
state_machine_regs.address);
- }
+ }
else
{
if (xop == -DW_LNE_end_sequence)
@@ -6073,7 +6073,7 @@ display_debug_macro (struct dwarf_sectio
load_debug_section_with_follow (str, file);
load_debug_section_with_follow (line, file);
load_debug_section_with_follow (str_index, file);
-
+
introduce (section, false);
while (curr < end)
@@ -6525,7 +6525,7 @@ display_loc_list (struct dwarf_section *
/* Check base address specifiers. */
if (is_max_address (begin, pointer_size)
- && !is_max_address (end, pointer_size))
+ && !is_max_address (end, pointer_size))
{
base_address = end;
print_dwarf_vma (begin, pointer_size);
@@ -6703,7 +6703,7 @@ display_loclists_list (struct dwarf_sect
case DW_LLE_default_location:
begin = end = 0;
break;
-
+
case DW_LLE_offset_pair:
READ_ULEB (begin, start, section_end);
begin += base_address;
@@ -6999,7 +6999,7 @@ display_offset_entry_loclists (struct dw
unsigned char * start = section->start;
unsigned char * const end = start + section->size;
- introduce (section, false);
+ introduce (section, false);
do
{
@@ -7048,14 +7048,14 @@ display_offset_entry_loclists (struct dw
section->name, segment_selector_size);
return 0;
}
-
+
if (offset_entry_count == 0)
{
warn (_("The %s section contains a table without offset\n"),
section->name);
return 0;
}
-
+
printf (_("\n Offset Entries starting at 0x%lx:\n"),
(long)(start - section->start));
@@ -8217,7 +8217,7 @@ display_debug_rnglists (struct dwarf_sec
start = display_debug_rnglists_list
(start, end, address_size, offset, 0, offset_size);
if (start >= end)
- break;
+ break;
}
start = end;
@@ -8335,12 +8335,12 @@ display_debug_ranges (struct dwarf_secti
next = section_begin + offset + debug_info_p->rnglists_base;
/* 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. */
+ 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;
+ continue;
last_offset = offset;
if (dwarf_check != 0 && i > 0)
@@ -10274,7 +10274,7 @@ display_debug_names (struct dwarf_sectio
printf (_("Out of %lu items there are %zu bucket clashes"
" (longest of %zu entries).\n"),
(unsigned long) name_count, hash_clash_count, longest_clash);
-
+
if (name_count != buckets_filled + hash_clash_count)
warn (_("The name_count (%lu) is not the same as the used bucket_count (%lu) + the hash clash count (%lu)"),
(unsigned long) name_count,
@@ -10378,7 +10378,7 @@ display_debug_names (struct dwarf_sectio
break;
if (tagno >= 0)
printf ("%s<%lu>",
- (tagno == 0 && second_abbrev_tag == 0 ? " " : "\n\t"),
+ (tagno == 0 && second_abbrev_tag == 0 ? " " : "\n\t"),
(unsigned long) abbrev_tag);
for (entry = abbrev_lookup;
@@ -10907,7 +10907,7 @@ process_cu_tu_index (struct dwarf_sectio
Check for integer overflow (can occur when size_t is 32-bit)
with overlarge ncols or nused values. */
if (nused == -1u
- || _mul_overflow ((size_t) ncols, 4, &temp)
+ || _mul_overflow ((size_t) ncols, 4, &temp)
|| _mul_overflow ((size_t) nused + 1, temp, &total)
|| total > (size_t) (limit - ppool))
{
@@ -10915,7 +10915,7 @@ process_cu_tu_index (struct dwarf_sectio
section->name);
return 0;
}
-
+
if (do_display)
{
printf (_(" Offset table\n"));
@@ -11419,8 +11419,8 @@ add_separate_debug_file (const char * fi
static bool
debuginfod_fetch_separate_debug_info (struct dwarf_section * section,
- char ** filename,
- void * file)
+ char ** filename,
+ void * file)
{
size_t build_id_len;
unsigned char * build_id;
@@ -11438,14 +11438,14 @@ debuginfod_fetch_separate_debug_info (st
filelen = strnlen ((const char *)section->start, section->size);
if (filelen == section->size)
- /* Corrupt debugaltlink. */
- return false;
+ /* Corrupt debugaltlink. */
+ return false;
build_id = section->start + filelen + 1;
build_id_len = section->size - (filelen + 1);
if (build_id_len == 0)
- return false;
+ return false;
}
else
return false;
@@ -11457,25 +11457,25 @@ debuginfod_fetch_separate_debug_info (st
client = debuginfod_begin ();
if (client == NULL)
- return false;
+ return false;
/* Query debuginfod servers for the target file. If found its path
- will be stored in filename. */
+ 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 (). */
+ in get_build_id (). */
if (build_id_len == 0)
- free (build_id);
+ 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;
- }
+ {
+ /* File successfully retrieved. Close fd since we want to
+ use open_debug_file () on filename instead. */
+ close (fd);
+ return true;
+ }
}
return false;
@@ -11488,7 +11488,7 @@ load_separate_debug_info (const char *
parse_func_type parse_func,
check_func_type check_func,
void * func_data,
- void * file ATTRIBUTE_UNUSED)
+ void * file ATTRIBUTE_UNUSED)
{
const char * separate_filename;
char * debug_filename;
@@ -11604,11 +11604,11 @@ load_separate_debug_info (const char *
& 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;
+ /* File successfully downloaded from server, replace
+ debug_filename with the file's path. */
+ free (debug_filename);
+ debug_filename = tmp_filename;
+ goto found;
}
}
#endif
@@ -11775,12 +11775,12 @@ load_build_id_debug_file (const char * m
/* In theory we should extract the contents of the section into
a note structure and then check the fields. For now though
just use hard coded offsets instead:
-
+
Field Bytes Contents
NSize 0...3 4
DSize 4...7 8+
Type 8..11 3 (NT_GNU_BUILD_ID)
- Name 12.15 GNU\0
+ Name 12.15 GNU\0
Data 16.... */
/* FIXME: Check the name size, name and type fields. */
@@ -11792,7 +11792,7 @@ load_build_id_debug_file (const char * m
warn (_(".note.gnu.build-id data size is too small\n"));
return;
}
-
+
if (build_id_size > (section->size - 16))
{
warn (_(".note.gnu.build-id data size is too bug\n"));
@@ -12088,10 +12088,6 @@ free_debug_memory (void)
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;

View File

@ -1,349 +0,0 @@
From f07c08e115e27cddf5a0030dc6332bbee1bd9c6a Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Thu, 21 Jul 2022 08:38:14 +0930
Subject: [PATCH] binutils/dwarf.c: abbrev caching
I'm inclined to think that abbrev caching is counter-productive. The
time taken to search the list of abbrevs converted to internal form is
non-zero, and it's easy to decode the raw abbrevs. It's especially
silly to cache empty lists of decoded abbrevs (happens with zero
padding in .debug_abbrev), or abbrevs as they are displayed when there
is no further use of those abbrevs. This patch stops caching in those
cases.
* dwarf.c (record_abbrev_list_for_cu): Add free_list param.
Put abbrevs on abbrev_lists here.
(new_abbrev_list): Delete function.
(process_abbrev_set): Return newly allocated list. Move
abbrev base, offset and size checking to..
(find_and_process_abbrev_set): ..here, new function. Handle
lookup of cached abbrevs here, and calculate start and end
for process_abbrev_set. Return free_list if newly alloc'd.
(process_debug_info): Consolidate cached list lookup, new list
alloc and processing into find_and_process_abbrev_set call.
Free list when not cached.
(display_debug_abbrev): Similarly.
---
binutils/dwarf.c | 208 +++++++++++++++++++++++++----------------------
1 file changed, 110 insertions(+), 98 deletions(-)
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 267ed3bb382..2fc352f74c5 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -882,8 +882,15 @@ static unsigned long next_free_abbrev_map_entry = 0;
#define ABBREV_MAP_ENTRIES_INCREMENT 8
static void
-record_abbrev_list_for_cu (dwarf_vma start, dwarf_vma end, abbrev_list * list)
+record_abbrev_list_for_cu (dwarf_vma start, dwarf_vma end,
+ abbrev_list *list, abbrev_list *free_list)
{
+ if (free_list != NULL)
+ {
+ list->next = abbrev_lists;
+ abbrev_lists = list;
+ }
+
if (cu_abbrev_map == NULL)
{
num_abbrev_map_entries = INITIAL_NUM_ABBREV_MAP_ENTRIES;
@@ -938,20 +945,6 @@ free_all_abbrevs (void)
next_free_abbrev_map_entry = 0;
}
-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)
@@ -969,7 +962,7 @@ find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base,
/* 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. */
+ Not caching abbrevs is likely the answer. */
static abbrev_map *
find_abbrev_map_by_offset (dwarf_vma offset)
@@ -1036,40 +1029,18 @@ add_abbrev_attr (unsigned long attribute,
list->last_abbrev->last_attr = attr;
}
-/* Processes the (partial) contents of a .debug_abbrev section.
- Returns NULL if the end of the section was encountered.
- Returns the address after the last byte read if the end of
- an abbreviation set was found. */
+/* Return processed (partial) contents of a .debug_abbrev section.
+ Returns NULL on errors. */
-static unsigned char *
+static abbrev_list *
process_abbrev_set (struct dwarf_section *section,
- dwarf_vma abbrev_base,
- dwarf_vma abbrev_size,
- dwarf_vma abbrev_offset,
- abbrev_list *list)
+ unsigned char *start,
+ unsigned char *end)
{
- if (abbrev_base >= section->size
- || abbrev_size > section->size - abbrev_base)
- {
- /* PR 17531: file:4bcd9ce9. */
- warn (_("Debug info is corrupted, abbrev size (%lx) is larger than "
- "abbrev section size (%lx)\n"),
- (unsigned long) (abbrev_base + abbrev_size),
- (unsigned long) section->size);
- return NULL;
- }
- if (abbrev_offset >= abbrev_size)
- {
- warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than "
- "abbrev section size (%lx)\n"),
- (unsigned long) abbrev_offset,
- (unsigned long) abbrev_size);
- return NULL;
- }
+ abbrev_list *list = xmalloc (sizeof (*list));
+ list->first_abbrev = NULL;
+ list->last_abbrev = NULL;
- unsigned char *start = section->start + abbrev_base;
- unsigned char *end = start + abbrev_size;
- start += abbrev_offset;
while (start < end)
{
unsigned long entry;
@@ -1082,14 +1053,18 @@ process_abbrev_set (struct dwarf_section *section,
/* 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)
- return NULL;
- if (entry == 0)
- return start;
+ if (start == end || entry == 0)
+ {
+ list->start_of_next_abbrevs = start != end ? start : NULL;
+ return list;
+ }
READ_ULEB (tag, start, end);
if (start == end)
- return NULL;
+ {
+ free (list);
+ return NULL;
+ }
children = *start++;
@@ -1124,9 +1099,67 @@ process_abbrev_set (struct dwarf_section *section,
/* Report the missing single zero which ends the section. */
error (_("%s section not zero terminated\n"), section->name);
+ free (list);
return NULL;
}
+/* Return a sequence of abbrevs in SECTION starting at ABBREV_BASE
+ plus ABBREV_OFFSET and finishing at ABBREV_BASE + ABBREV_SIZE.
+ If FREE_LIST is non-NULL search the already decoded abbrevs on
+ abbrev_lists first and if found set *FREE_LIST to NULL. If
+ searching doesn't find a matching abbrev, set *FREE_LIST to the
+ newly allocated list. If FREE_LIST is NULL, no search is done and
+ the returned abbrev_list is always newly allocated. */
+
+static abbrev_list *
+find_and_process_abbrev_set (struct dwarf_section *section,
+ dwarf_vma abbrev_base,
+ dwarf_vma abbrev_size,
+ dwarf_vma abbrev_offset,
+ abbrev_list **free_list)
+{
+ if (free_list)
+ *free_list = NULL;
+
+ if (abbrev_base >= section->size
+ || abbrev_size > section->size - abbrev_base)
+ {
+ /* PR 17531: file:4bcd9ce9. */
+ warn (_("Debug info is corrupted, abbrev size (%lx) is larger than "
+ "abbrev section size (%lx)\n"),
+ (unsigned long) (abbrev_base + abbrev_size),
+ (unsigned long) section->size);
+ return NULL;
+ }
+ if (abbrev_offset >= abbrev_size)
+ {
+ warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than "
+ "abbrev section size (%lx)\n"),
+ (unsigned long) abbrev_offset,
+ (unsigned long) abbrev_size);
+ return NULL;
+ }
+
+ unsigned char *start = section->start + abbrev_base + abbrev_offset;
+ unsigned char *end = section->start + abbrev_base + abbrev_size;
+ abbrev_list *list = NULL;
+ if (free_list)
+ list = find_abbrev_list_by_abbrev_offset (abbrev_base, abbrev_offset);
+ if (list == NULL)
+ {
+ list = process_abbrev_set (section, start, end);
+ if (list)
+ {
+ list->abbrev_base = abbrev_base;
+ list->abbrev_offset = abbrev_offset;
+ list->next = NULL;
+ }
+ if (free_list)
+ *free_list = list;
+ }
+ return list;
+}
+
static const char *
get_TAG_name (unsigned long tag)
{
@@ -3671,7 +3704,6 @@ process_debug_info (struct dwarf_section * section,
dwarf_vma cu_offset;
unsigned int offset_size;
struct cu_tu_set * this_set;
- abbrev_list * list;
unsigned char *end_cu;
hdrptr = start;
@@ -3727,22 +3759,18 @@ process_debug_info (struct dwarf_section * section,
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 (&debug_displays[abbrev_sec].section,
- abbrev_base, abbrev_size,
- compunit.cu_abbrev_offset, list);
- list->start_of_next_abbrevs = next;
- }
-
+ abbrev_list *list;
+ abbrev_list *free_list;
+ list = find_and_process_abbrev_set (&debug_displays[abbrev_sec].section,
+ abbrev_base, abbrev_size,
+ compunit.cu_abbrev_offset,
+ &free_list);
start = end_cu;
- record_abbrev_list_for_cu (cu_offset, start - section_begin, list);
+ if (list != NULL && list->first_abbrev != NULL)
+ record_abbrev_list_for_cu (cu_offset, start - section_begin,
+ list, free_list);
+ else if (free_list != NULL)
+ free_abbrev_list (free_list);
}
for (start = section_begin, unit = 0; start < end; unit++)
@@ -3758,7 +3786,6 @@ process_debug_info (struct dwarf_section * section,
struct cu_tu_set *this_set;
dwarf_vma abbrev_base;
size_t abbrev_size;
- abbrev_list * list = NULL;
unsigned char *end_cu;
hdrptr = start;
@@ -3937,20 +3964,10 @@ process_debug_info (struct dwarf_section * section,
}
/* Process the abbrevs used by this compilation unit. */
- 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 (&debug_displays[abbrev_sec].section,
- abbrev_base, abbrev_size,
- compunit.cu_abbrev_offset, list);
- list->start_of_next_abbrevs = next;
- }
-
+ abbrev_list *list;
+ list = find_and_process_abbrev_set (&debug_displays[abbrev_sec].section,
+ abbrev_base, abbrev_size,
+ compunit.cu_abbrev_offset, NULL);
level = 0;
last_level = level;
saved_level = -1;
@@ -4128,6 +4145,8 @@ process_debug_info (struct dwarf_section * section,
if (entry->children)
++level;
}
+ if (list != NULL)
+ free_abbrev_list (list);
}
/* Set num_debug_info_entries here so that it can be used to check if
@@ -6353,24 +6372,15 @@ display_debug_abbrev (struct dwarf_section *section,
do
{
- abbrev_list * list;
- dwarf_vma offset;
-
- offset = start - section->start;
- list = find_abbrev_list_by_abbrev_offset (0, offset);
+ dwarf_vma offset = start - section->start;
+ abbrev_list *list = find_and_process_abbrev_set (section, 0,
+ section->size, offset,
+ NULL);
if (list == NULL)
- {
- list = new_abbrev_list (0, offset);
- start = process_abbrev_set (section, 0, section->size, offset, list);
- list->start_of_next_abbrevs = start;
- }
- else
- start = list->start_of_next_abbrevs;
-
- if (list->first_abbrev == NULL)
- continue;
+ break;
- printf (_(" Number TAG (0x%lx)\n"), (long) offset);
+ if (list->first_abbrev)
+ printf (_(" Number TAG (0x%lx)\n"), (long) offset);
for (entry = list->first_abbrev; entry; entry = entry->next)
{
@@ -6391,6 +6401,8 @@ display_debug_abbrev (struct dwarf_section *section,
putchar ('\n');
}
}
+ start = list->start_of_next_abbrevs;
+ free_abbrev_list (list);
}
while (start);
--
2.31.1

View File

@ -1,96 +0,0 @@
Aka bsc#1203016
From 695c6dfe7e85006b98c8b746f3fd5f913c94ebff Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Thu, 21 Jul 2022 09:56:15 +0930
Subject: [PATCH] PR29370, infinite loop in display_debug_abbrev
The PR29370 testcase is a fuzzed object file with multiple
.trace_abbrev sections. Multiple .trace_abbrev or .debug_abbrev
sections are not a violation of the DWARF standard. The DWARF5
standard even gives an example of multiple .debug_abbrev sections
contained in groups. Caching and lookup of processed abbrevs thus
needs to be done by section and offset rather than base and offset.
(Why base anyway?) Or, since section contents are kept, by a pointer
into the contents.
PR 29370
* dwarf.c (struct abbrev_list): Replace abbrev_base and
abbrev_offset with raw field.
(find_abbrev_list_by_abbrev_offset): Delete.
(find_abbrev_list_by_raw_abbrev): New function.
(process_abbrev_set): Set list->raw and list->next.
(find_and_process_abbrev_set): Replace abbrev list lookup with
new function. Don't set list abbrev_base, abbrev_offset or next.
---
binutils/dwarf.c | 19 ++++++-------------
1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 2fc352f74c5..99fb3566994 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -856,8 +856,7 @@ typedef struct abbrev_list
{
abbrev_entry * first_abbrev;
abbrev_entry * last_abbrev;
- dwarf_vma abbrev_base;
- dwarf_vma abbrev_offset;
+ unsigned char * raw;
struct abbrev_list * next;
unsigned char * start_of_next_abbrevs;
}
@@ -946,14 +945,12 @@ free_all_abbrevs (void)
}
static abbrev_list *
-find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base,
- dwarf_vma abbrev_offset)
+find_abbrev_list_by_raw_abbrev (unsigned char *raw)
{
abbrev_list * list;
for (list = abbrev_lists; list != NULL; list = list->next)
- if (list->abbrev_base == abbrev_base
- && list->abbrev_offset == abbrev_offset)
+ if (list->raw == raw)
return list;
return NULL;
@@ -1040,6 +1037,7 @@ process_abbrev_set (struct dwarf_section *section,
abbrev_list *list = xmalloc (sizeof (*list));
list->first_abbrev = NULL;
list->last_abbrev = NULL;
+ list->raw = start;
while (start < end)
{
@@ -1055,6 +1053,7 @@ process_abbrev_set (struct dwarf_section *section,
the caller. */
if (start == end || entry == 0)
{
+ list->next = NULL;
list->start_of_next_abbrevs = start != end ? start : NULL;
return list;
}
@@ -1144,16 +1143,10 @@ find_and_process_abbrev_set (struct dwarf_section *section,
unsigned char *end = section->start + abbrev_base + abbrev_size;
abbrev_list *list = NULL;
if (free_list)
- list = find_abbrev_list_by_abbrev_offset (abbrev_base, abbrev_offset);
+ list = find_abbrev_list_by_raw_abbrev (start);
if (list == NULL)
{
list = process_abbrev_set (section, start, end);
- if (list)
- {
- list->abbrev_base = abbrev_base;
- list->abbrev_offset = abbrev_offset;
- list->next = NULL;
- }
if (free_list)
*free_list = list;
}
--
2.31.1

View File

@ -1,10 +1,3 @@
-------------------------------------------------------------------
Thu Sep 1 11:52:52 UTC 2022 - Michael Matz <matz@suse.com>
- Add binutils-pr29370.diff and their prerequisites
binutils-pr29370-pre1.diff and binutils-pr29370-pre2.diff
for PR29370, aka CVE-2022-38128 [bsc#1203016]
-------------------------------------------------------------------
Fri Aug 26 13:24:35 UTC 2022 - Michael Matz <matz@suse.com>

View File

@ -139,9 +139,6 @@ Patch41: binutils-fix-relax.diff
Patch42: binutils-compat-old-behaviour.diff
Patch43: binutils-revert-hlasm-insns.diff
Patch44: binutils-pr29482.diff
Patch45: binutils-pr29370-pre1.diff
Patch46: binutils-pr29370-pre2.diff
Patch47: binutils-pr29370.diff
Patch100: add-ulp-section.diff
Patch90: cross-avr-nesc-as.patch
Patch92: cross-avr-omit_section_dynsym.patch
@ -265,9 +262,6 @@ cp ld/ldgram.y ld/ldgram.y.orig
%patch43 -p1
%endif
%patch44 -p1
%patch45 -p1
%patch46 -p1
%patch47 -p1
%patch100 -p1
%if "%{TARGET}" == "avr"
cp gas/config/tc-avr.h gas/config/tc-avr-nesc.h