|
|
5be97c |
diff -rup binutils.orig/bfd/dwarf2.c binutils-2.36.1/bfd/dwarf2.c
|
|
|
5be97c |
--- binutils.orig/bfd/dwarf2.c 2022-04-11 12:06:47.745972052 +0100
|
|
|
5be97c |
+++ binutils-2.36.1/bfd/dwarf2.c 2022-04-11 12:58:03.964445150 +0100
|
|
|
5be97c |
@@ -1484,6 +1484,8 @@ struct funcinfo
|
|
|
5be97c |
struct arange arange;
|
|
|
5be97c |
/* Where the symbol is defined. */
|
|
|
5be97c |
asection * sec;
|
|
|
5be97c |
+ /* The offset of the funcinfo from the start of the unit. */
|
|
|
5be97c |
+ bfd_uint64_t unit_offset;
|
|
|
5be97c |
};
|
|
|
5be97c |
|
|
|
5be97c |
struct lookup_funcinfo
|
|
|
5be97c |
@@ -3304,6 +3306,15 @@ read_rangelist (struct comp_unit *unit,
|
|
|
5be97c |
return read_rnglists (unit, arange, offset);
|
|
|
5be97c |
}
|
|
|
5be97c |
|
|
|
5be97c |
+static struct funcinfo *
|
|
|
5be97c |
+lookup_func_by_offset (bfd_uint64_t offset, struct funcinfo * table)
|
|
|
5be97c |
+{
|
|
|
5be97c |
+ for (; table != NULL; table = table->prev_func)
|
|
|
5be97c |
+ if (table->unit_offset == offset)
|
|
|
5be97c |
+ return table;
|
|
|
5be97c |
+ return NULL;
|
|
|
5be97c |
+}
|
|
|
5be97c |
+
|
|
|
5be97c |
static struct varinfo *
|
|
|
5be97c |
lookup_var_by_offset (bfd_uint64_t offset, struct varinfo * table)
|
|
|
5be97c |
{
|
|
|
5be97c |
@@ -3317,6 +3328,35 @@ lookup_var_by_offset (bfd_uint64_t offse
|
|
|
5be97c |
return NULL;
|
|
|
5be97c |
}
|
|
|
5be97c |
|
|
|
5be97c |
+static struct funcinfo *
|
|
|
5be97c |
+reverse_funcinfo_list (struct funcinfo * head)
|
|
|
5be97c |
+{
|
|
|
5be97c |
+ struct funcinfo * rhead;
|
|
|
5be97c |
+ struct funcinfo * temp;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ for (rhead = NULL; head; head = temp)
|
|
|
5be97c |
+ {
|
|
|
5be97c |
+ temp = head->prev_func;
|
|
|
5be97c |
+ head->prev_func = rhead;
|
|
|
5be97c |
+ rhead = head;
|
|
|
5be97c |
+ }
|
|
|
5be97c |
+ return rhead;
|
|
|
5be97c |
+}
|
|
|
5be97c |
+
|
|
|
5be97c |
+static struct varinfo *
|
|
|
5be97c |
+reverse_varinfo_list (struct varinfo * head)
|
|
|
5be97c |
+{
|
|
|
5be97c |
+ struct varinfo * rhead;
|
|
|
5be97c |
+ struct varinfo * temp;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ for (rhead = NULL; head; head = temp)
|
|
|
5be97c |
+ {
|
|
|
5be97c |
+ temp = head->prev_var;
|
|
|
5be97c |
+ head->prev_var = rhead;
|
|
|
5be97c |
+ rhead = head;
|
|
|
5be97c |
+ }
|
|
|
5be97c |
+ return rhead;
|
|
|
5be97c |
+}
|
|
|
5be97c |
|
|
|
5be97c |
/* DWARF2 Compilation unit functions. */
|
|
|
5be97c |
|
|
|
5be97c |
@@ -3334,6 +3374,8 @@ scan_unit_for_symbols (struct comp_unit
|
|
|
5be97c |
struct funcinfo *func;
|
|
|
5be97c |
} *nested_funcs;
|
|
|
5be97c |
int nested_funcs_size;
|
|
|
5be97c |
+ struct funcinfo *last_func;
|
|
|
5be97c |
+ struct varinfo *last_var;
|
|
|
5be97c |
|
|
|
5be97c |
/* Maintain a stack of in-scope functions and inlined functions, which we
|
|
|
5be97c |
can use to set the caller_func field. */
|
|
|
5be97c |
@@ -3344,16 +3386,16 @@ scan_unit_for_symbols (struct comp_unit
|
|
|
5be97c |
return FALSE;
|
|
|
5be97c |
nested_funcs[nesting_level].func = 0;
|
|
|
5be97c |
|
|
|
5be97c |
+ /* PR 27484: We must scan the DIEs twice. The first time we look for
|
|
|
5be97c |
+ function and variable tags and accumulate them into their respective
|
|
|
5be97c |
+ tables. The second time through we process the attributes of the
|
|
|
5be97c |
+ functions/variables and augment the table entries. */
|
|
|
5be97c |
while (nesting_level >= 0)
|
|
|
5be97c |
{
|
|
|
5be97c |
unsigned int abbrev_number, bytes_read, i;
|
|
|
5be97c |
struct abbrev_info *abbrev;
|
|
|
5be97c |
- struct attribute attr;
|
|
|
5be97c |
struct funcinfo *func;
|
|
|
5be97c |
struct varinfo *var;
|
|
|
5be97c |
- bfd_vma low_pc = 0;
|
|
|
5be97c |
- bfd_vma high_pc = 0;
|
|
|
5be97c |
- bfd_boolean high_pc_relative = FALSE;
|
|
|
5be97c |
bfd_uint64_t current_offset;
|
|
|
5be97c |
|
|
|
5be97c |
/* PR 17512: file: 9f405d9d. */
|
|
|
5be97c |
@@ -3400,6 +3442,7 @@ scan_unit_for_symbols (struct comp_unit
|
|
|
5be97c |
goto fail;
|
|
|
5be97c |
func->tag = abbrev->tag;
|
|
|
5be97c |
func->prev_func = unit->function_table;
|
|
|
5be97c |
+ func->unit_offset = current_offset;
|
|
|
5be97c |
unit->function_table = func;
|
|
|
5be97c |
unit->number_of_functions++;
|
|
|
5be97c |
BFD_ASSERT (!unit->cached);
|
|
|
5be97c |
@@ -3440,6 +3483,111 @@ scan_unit_for_symbols (struct comp_unit
|
|
|
5be97c |
|
|
|
5be97c |
for (i = 0; i < abbrev->num_attrs; ++i)
|
|
|
5be97c |
{
|
|
|
5be97c |
+ struct attribute attr;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ info_ptr = read_attribute (&attr, &abbrev->attrs[i],
|
|
|
5be97c |
+ unit, info_ptr, info_ptr_end);
|
|
|
5be97c |
+ if (info_ptr == NULL)
|
|
|
5be97c |
+ goto fail;
|
|
|
5be97c |
+ }
|
|
|
5be97c |
+
|
|
|
5be97c |
+ if (abbrev->has_children)
|
|
|
5be97c |
+ {
|
|
|
5be97c |
+ nesting_level++;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ if (nesting_level >= nested_funcs_size)
|
|
|
5be97c |
+ {
|
|
|
5be97c |
+ struct nest_funcinfo *tmp;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ nested_funcs_size *= 2;
|
|
|
5be97c |
+ tmp = (struct nest_funcinfo *)
|
|
|
5be97c |
+ bfd_realloc (nested_funcs,
|
|
|
5be97c |
+ nested_funcs_size * sizeof (*nested_funcs));
|
|
|
5be97c |
+ if (tmp == NULL)
|
|
|
5be97c |
+ goto fail;
|
|
|
5be97c |
+ nested_funcs = tmp;
|
|
|
5be97c |
+ }
|
|
|
5be97c |
+ nested_funcs[nesting_level].func = 0;
|
|
|
5be97c |
+ }
|
|
|
5be97c |
+ }
|
|
|
5be97c |
+
|
|
|
5be97c |
+ unit->function_table = reverse_funcinfo_list (unit->function_table);
|
|
|
5be97c |
+ unit->variable_table = reverse_varinfo_list (unit->variable_table);
|
|
|
5be97c |
+
|
|
|
5be97c |
+ /* This is the second pass over the abbrevs. */
|
|
|
5be97c |
+ info_ptr = unit->first_child_die_ptr;
|
|
|
5be97c |
+ nesting_level = 0;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ last_func = NULL;
|
|
|
5be97c |
+ last_var = NULL;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ while (nesting_level >= 0)
|
|
|
5be97c |
+ {
|
|
|
5be97c |
+ unsigned int abbrev_number, bytes_read, i;
|
|
|
5be97c |
+ struct abbrev_info *abbrev;
|
|
|
5be97c |
+ struct attribute attr;
|
|
|
5be97c |
+ struct funcinfo *func;
|
|
|
5be97c |
+ struct varinfo *var;
|
|
|
5be97c |
+ bfd_vma low_pc = 0;
|
|
|
5be97c |
+ bfd_vma high_pc = 0;
|
|
|
5be97c |
+ bfd_boolean high_pc_relative = FALSE;
|
|
|
5be97c |
+ bfd_uint64_t current_offset;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ /* PR 17512: file: 9f405d9d. */
|
|
|
5be97c |
+ if (info_ptr >= info_ptr_end)
|
|
|
5be97c |
+ goto fail;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ current_offset = info_ptr - unit->info_ptr_unit;
|
|
|
5be97c |
+ abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
|
|
|
5be97c |
+ FALSE, info_ptr_end);
|
|
|
5be97c |
+ info_ptr += bytes_read;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ if (! abbrev_number)
|
|
|
5be97c |
+ {
|
|
|
5be97c |
+ nesting_level--;
|
|
|
5be97c |
+ continue;
|
|
|
5be97c |
+ }
|
|
|
5be97c |
+
|
|
|
5be97c |
+ abbrev = lookup_abbrev (abbrev_number, unit->abbrevs);
|
|
|
5be97c |
+ /* This should have been handled above. */
|
|
|
5be97c |
+ BFD_ASSERT (abbrev != NULL);
|
|
|
5be97c |
+
|
|
|
5be97c |
+ func = NULL;
|
|
|
5be97c |
+ var = NULL;
|
|
|
5be97c |
+ if (abbrev->tag == DW_TAG_subprogram
|
|
|
5be97c |
+ || abbrev->tag == DW_TAG_entry_point
|
|
|
5be97c |
+ || abbrev->tag == DW_TAG_inlined_subroutine)
|
|
|
5be97c |
+ {
|
|
|
5be97c |
+ if (last_func
|
|
|
5be97c |
+ && last_func->prev_func
|
|
|
5be97c |
+ && last_func->prev_func->unit_offset == current_offset)
|
|
|
5be97c |
+ func = last_func->prev_func;
|
|
|
5be97c |
+ else
|
|
|
5be97c |
+ func = lookup_func_by_offset (current_offset, unit->function_table);
|
|
|
5be97c |
+
|
|
|
5be97c |
+ if (func == NULL)
|
|
|
5be97c |
+ goto fail;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ last_func = func;
|
|
|
5be97c |
+ }
|
|
|
5be97c |
+ else if (abbrev->tag == DW_TAG_variable
|
|
|
5be97c |
+ || abbrev->tag == DW_TAG_member)
|
|
|
5be97c |
+ {
|
|
|
5be97c |
+ if (last_var
|
|
|
5be97c |
+ && last_var->prev_var
|
|
|
5be97c |
+ && last_var->prev_var->unit_offset == current_offset)
|
|
|
5be97c |
+ var = last_var->prev_var;
|
|
|
5be97c |
+ else
|
|
|
5be97c |
+ var = lookup_var_by_offset (current_offset, unit->variable_table);
|
|
|
5be97c |
+
|
|
|
5be97c |
+ if (var == NULL)
|
|
|
5be97c |
+ goto fail;
|
|
|
5be97c |
+
|
|
|
5be97c |
+ last_var = var;
|
|
|
5be97c |
+ }
|
|
|
5be97c |
+
|
|
|
5be97c |
+ for (i = 0; i < abbrev->num_attrs; ++i)
|
|
|
5be97c |
+ {
|
|
|
5be97c |
info_ptr = read_attribute (&attr, &abbrev->attrs[i],
|
|
|
5be97c |
unit, info_ptr, info_ptr_end);
|
|
|
5be97c |
if (info_ptr == NULL)
|
|
|
5be97c |
@@ -3604,6 +3752,9 @@ scan_unit_for_symbols (struct comp_unit
|
|
|
5be97c |
}
|
|
|
5be97c |
}
|
|
|
5be97c |
|
|
|
5be97c |
+ if (abbrev->has_children)
|
|
|
5be97c |
+ nesting_level++;
|
|
|
5be97c |
+
|
|
|
5be97c |
if (high_pc_relative)
|
|
|
5be97c |
high_pc += low_pc;
|
|
|
5be97c |
|
|
|
5be97c |
@@ -3612,27 +3763,11 @@ scan_unit_for_symbols (struct comp_unit
|
|
|
5be97c |
if (!arange_add (unit, &func->arange, low_pc, high_pc))
|
|
|
5be97c |
goto fail;
|
|
|
5be97c |
}
|
|
|
5be97c |
-
|
|
|
5be97c |
- if (abbrev->has_children)
|
|
|
5be97c |
- {
|
|
|
5be97c |
- nesting_level++;
|
|
|
5be97c |
-
|
|
|
5be97c |
- if (nesting_level >= nested_funcs_size)
|
|
|
5be97c |
- {
|
|
|
5be97c |
- struct nest_funcinfo *tmp;
|
|
|
5be97c |
-
|
|
|
5be97c |
- nested_funcs_size *= 2;
|
|
|
5be97c |
- tmp = (struct nest_funcinfo *)
|
|
|
5be97c |
- bfd_realloc (nested_funcs,
|
|
|
5be97c |
- nested_funcs_size * sizeof (*nested_funcs));
|
|
|
5be97c |
- if (tmp == NULL)
|
|
|
5be97c |
- goto fail;
|
|
|
5be97c |
- nested_funcs = tmp;
|
|
|
5be97c |
- }
|
|
|
5be97c |
- nested_funcs[nesting_level].func = 0;
|
|
|
5be97c |
- }
|
|
|
5be97c |
}
|
|
|
5be97c |
|
|
|
5be97c |
+ unit->function_table = reverse_funcinfo_list (unit->function_table);
|
|
|
5be97c |
+ unit->variable_table = reverse_varinfo_list (unit->variable_table);
|
|
|
5be97c |
+
|
|
|
5be97c |
free (nested_funcs);
|
|
|
5be97c |
return TRUE;
|
|
|
5be97c |
|
|
|
5be97c |
@@ -3994,36 +4129,6 @@ comp_unit_find_line (struct comp_unit *u
|
|
|
5be97c |
linenumber_ptr);
|
|
|
5be97c |
}
|
|
|
5be97c |
|
|
|
5be97c |
-static struct funcinfo *
|
|
|
5be97c |
-reverse_funcinfo_list (struct funcinfo *head)
|
|
|
5be97c |
-{
|
|
|
5be97c |
- struct funcinfo *rhead;
|
|
|
5be97c |
- struct funcinfo *temp;
|
|
|
5be97c |
-
|
|
|
5be97c |
- for (rhead = NULL; head; head = temp)
|
|
|
5be97c |
- {
|
|
|
5be97c |
- temp = head->prev_func;
|
|
|
5be97c |
- head->prev_func = rhead;
|
|
|
5be97c |
- rhead = head;
|
|
|
5be97c |
- }
|
|
|
5be97c |
- return rhead;
|
|
|
5be97c |
-}
|
|
|
5be97c |
-
|
|
|
5be97c |
-static struct varinfo *
|
|
|
5be97c |
-reverse_varinfo_list (struct varinfo *head)
|
|
|
5be97c |
-{
|
|
|
5be97c |
- struct varinfo *rhead;
|
|
|
5be97c |
- struct varinfo *temp;
|
|
|
5be97c |
-
|
|
|
5be97c |
- for (rhead = NULL; head; head = temp)
|
|
|
5be97c |
- {
|
|
|
5be97c |
- temp = head->prev_var;
|
|
|
5be97c |
- head->prev_var = rhead;
|
|
|
5be97c |
- rhead = head;
|
|
|
5be97c |
- }
|
|
|
5be97c |
- return rhead;
|
|
|
5be97c |
-}
|
|
|
5be97c |
-
|
|
|
5be97c |
/* Extract all interesting funcinfos and varinfos of a compilation
|
|
|
5be97c |
unit into hash tables for faster lookup. Returns TRUE if no
|
|
|
5be97c |
errors were enountered; FALSE otherwise. */
|