mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-27 22:48:57 +08:00
Reduce O(n2) performance overhead when parsing DWARF unit information.
PR 28978 * dwarf2.c (scan_unit_for_symbols): When performing second pass, check to see if the function or variable being processed is the same as the previous one.
This commit is contained in:

committed by
Nick Clifton

parent
46fb6d5aa2
commit
30cbd32aec
@ -1,3 +1,10 @@
|
|||||||
|
2022-03-21 Steiner H Gunderson <steinar+sourceware@gunderson.no>
|
||||||
|
|
||||||
|
PR 28978
|
||||||
|
* dwarf2.c (scan_unit_for_symbols): When performing second pass,
|
||||||
|
check to see if the function or variable being processed is the
|
||||||
|
same as the previous one.
|
||||||
|
|
||||||
2022-03-18 Viorel Preoteasa <viorel.preoteasa@gmail.com>
|
2022-03-18 Viorel Preoteasa <viorel.preoteasa@gmail.com>
|
||||||
|
|
||||||
PR 28924
|
PR 28924
|
||||||
|
87
bfd/dwarf2.c
87
bfd/dwarf2.c
@ -3293,6 +3293,36 @@ lookup_var_by_offset (bfd_uint64_t offset, struct varinfo * table)
|
|||||||
|
|
||||||
/* DWARF2 Compilation unit functions. */
|
/* DWARF2 Compilation unit functions. */
|
||||||
|
|
||||||
|
static struct funcinfo *
|
||||||
|
reverse_funcinfo_list (struct funcinfo *head)
|
||||||
|
{
|
||||||
|
struct funcinfo *rhead;
|
||||||
|
struct funcinfo *temp;
|
||||||
|
|
||||||
|
for (rhead = NULL; head; head = temp)
|
||||||
|
{
|
||||||
|
temp = head->prev_func;
|
||||||
|
head->prev_func = rhead;
|
||||||
|
rhead = head;
|
||||||
|
}
|
||||||
|
return rhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct varinfo *
|
||||||
|
reverse_varinfo_list (struct varinfo *head)
|
||||||
|
{
|
||||||
|
struct varinfo *rhead;
|
||||||
|
struct varinfo *temp;
|
||||||
|
|
||||||
|
for (rhead = NULL; head; head = temp)
|
||||||
|
{
|
||||||
|
temp = head->prev_var;
|
||||||
|
head->prev_var = rhead;
|
||||||
|
rhead = head;
|
||||||
|
}
|
||||||
|
return rhead;
|
||||||
|
}
|
||||||
|
|
||||||
/* Scan over each die in a comp. unit looking for functions to add
|
/* Scan over each die in a comp. unit looking for functions to add
|
||||||
to the function table and variables to the variable table. */
|
to the function table and variables to the variable table. */
|
||||||
|
|
||||||
@ -3308,6 +3338,8 @@ scan_unit_for_symbols (struct comp_unit *unit)
|
|||||||
struct funcinfo *func;
|
struct funcinfo *func;
|
||||||
} *nested_funcs;
|
} *nested_funcs;
|
||||||
int nested_funcs_size;
|
int nested_funcs_size;
|
||||||
|
struct funcinfo *last_func;
|
||||||
|
struct varinfo *last_var;
|
||||||
|
|
||||||
/* Maintain a stack of in-scope functions and inlined functions, which we
|
/* Maintain a stack of in-scope functions and inlined functions, which we
|
||||||
can use to set the caller_func field. */
|
can use to set the caller_func field. */
|
||||||
@ -3442,10 +3474,16 @@ scan_unit_for_symbols (struct comp_unit *unit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unit->function_table = reverse_funcinfo_list (unit->function_table);
|
||||||
|
unit->variable_table = reverse_varinfo_list (unit->variable_table);
|
||||||
|
|
||||||
/* This is the second pass over the abbrevs. */
|
/* This is the second pass over the abbrevs. */
|
||||||
info_ptr = unit->first_child_die_ptr;
|
info_ptr = unit->first_child_die_ptr;
|
||||||
nesting_level = 0;
|
nesting_level = 0;
|
||||||
|
|
||||||
|
last_func = NULL;
|
||||||
|
last_var = NULL;
|
||||||
|
|
||||||
while (nesting_level >= 0)
|
while (nesting_level >= 0)
|
||||||
{
|
{
|
||||||
unsigned int abbrev_number, i;
|
unsigned int abbrev_number, i;
|
||||||
@ -3481,16 +3519,32 @@ scan_unit_for_symbols (struct comp_unit *unit)
|
|||||||
|| abbrev->tag == DW_TAG_entry_point
|
|| abbrev->tag == DW_TAG_entry_point
|
||||||
|| abbrev->tag == DW_TAG_inlined_subroutine)
|
|| abbrev->tag == DW_TAG_inlined_subroutine)
|
||||||
{
|
{
|
||||||
|
if (last_func
|
||||||
|
&& last_func->prev_func
|
||||||
|
&& last_func->prev_func->unit_offset == current_offset)
|
||||||
|
func = last_func->prev_func;
|
||||||
|
else
|
||||||
func = lookup_func_by_offset (current_offset, unit->function_table);
|
func = lookup_func_by_offset (current_offset, unit->function_table);
|
||||||
|
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
last_func = func;
|
||||||
}
|
}
|
||||||
else if (abbrev->tag == DW_TAG_variable
|
else if (abbrev->tag == DW_TAG_variable
|
||||||
|| abbrev->tag == DW_TAG_member)
|
|| abbrev->tag == DW_TAG_member)
|
||||||
{
|
{
|
||||||
|
if (last_var
|
||||||
|
&& last_var->prev_var
|
||||||
|
&& last_var->prev_var->unit_offset == current_offset)
|
||||||
|
var = last_var->prev_var;
|
||||||
|
else
|
||||||
var = lookup_var_by_offset (current_offset, unit->variable_table);
|
var = lookup_var_by_offset (current_offset, unit->variable_table);
|
||||||
|
|
||||||
if (var == NULL)
|
if (var == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
last_var = var;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < abbrev->num_attrs; ++i)
|
for (i = 0; i < abbrev->num_attrs; ++i)
|
||||||
@ -3684,6 +3738,9 @@ scan_unit_for_symbols (struct comp_unit *unit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unit->function_table = reverse_funcinfo_list (unit->function_table);
|
||||||
|
unit->variable_table = reverse_varinfo_list (unit->variable_table);
|
||||||
|
|
||||||
free (nested_funcs);
|
free (nested_funcs);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -4047,36 +4104,6 @@ comp_unit_find_line (struct comp_unit *unit,
|
|||||||
linenumber_ptr);
|
linenumber_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct funcinfo *
|
|
||||||
reverse_funcinfo_list (struct funcinfo *head)
|
|
||||||
{
|
|
||||||
struct funcinfo *rhead;
|
|
||||||
struct funcinfo *temp;
|
|
||||||
|
|
||||||
for (rhead = NULL; head; head = temp)
|
|
||||||
{
|
|
||||||
temp = head->prev_func;
|
|
||||||
head->prev_func = rhead;
|
|
||||||
rhead = head;
|
|
||||||
}
|
|
||||||
return rhead;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct varinfo *
|
|
||||||
reverse_varinfo_list (struct varinfo *head)
|
|
||||||
{
|
|
||||||
struct varinfo *rhead;
|
|
||||||
struct varinfo *temp;
|
|
||||||
|
|
||||||
for (rhead = NULL; head; head = temp)
|
|
||||||
{
|
|
||||||
temp = head->prev_var;
|
|
||||||
head->prev_var = rhead;
|
|
||||||
rhead = head;
|
|
||||||
}
|
|
||||||
return rhead;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extract all interesting funcinfos and varinfos of a compilation
|
/* Extract all interesting funcinfos and varinfos of a compilation
|
||||||
unit into hash tables for faster lookup. Returns TRUE if no
|
unit into hash tables for faster lookup. Returns TRUE if no
|
||||||
errors were enountered; FALSE otherwise. */
|
errors were enountered; FALSE otherwise. */
|
||||||
|
Reference in New Issue
Block a user