diff options
author | Steiner H Gunderson <steinar+sourceware@gunderson.no> | 2022-03-21 14:29:12 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2022-03-21 14:29:12 +0000 |
commit | 30cbd32aec30b4bc13427bbd87c4c63c739d4578 (patch) | |
tree | 8dbe289e2e45bc6ecf2f0ed476f847dea656d34f /bfd | |
parent | 46fb6d5aa27d7129f472729a4f7ab8aa103aa674 (diff) | |
download | gdb-30cbd32aec30b4bc13427bbd87c4c63c739d4578.zip gdb-30cbd32aec30b4bc13427bbd87c4c63c739d4578.tar.gz gdb-30cbd32aec30b4bc13427bbd87c4c63c739d4578.tar.bz2 |
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.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/dwarf2.c | 93 |
2 files changed, 67 insertions, 33 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6ac8b96..fcf5aba 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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> PR 28924 diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index fdf071c..bb17679 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -3293,6 +3293,36 @@ lookup_var_by_offset (bfd_uint64_t offset, struct varinfo * table) /* 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 to the function table and variables to the variable table. */ @@ -3308,7 +3338,9 @@ scan_unit_for_symbols (struct comp_unit *unit) struct funcinfo *func; } *nested_funcs; int nested_funcs_size; - + struct funcinfo *last_func; + struct varinfo *last_var; + /* Maintain a stack of in-scope functions and inlined functions, which we can use to set the caller_func field. */ nested_funcs_size = 32; @@ -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. */ info_ptr = unit->first_child_die_ptr; nesting_level = 0; + last_func = NULL; + last_var = NULL; + while (nesting_level >= 0) { 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_inlined_subroutine) { - func = lookup_func_by_offset (current_offset, unit->function_table); + 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); + if (func == NULL) goto fail; + + last_func = func; } else if (abbrev->tag == DW_TAG_variable || abbrev->tag == DW_TAG_member) { - var = lookup_var_by_offset (current_offset, unit->variable_table); + 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); + if (var == NULL) goto fail; + + last_var = var; } 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); return true; @@ -4047,36 +4104,6 @@ comp_unit_find_line (struct comp_unit *unit, 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 unit into hash tables for faster lookup. Returns TRUE if no errors were enountered; FALSE otherwise. */ |