forked from pool/binutils
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:
parent
8d8118647c
commit
9460b44a5c
@ -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;
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user