Fix addr2line -i problem; reports incorrect function nesting for inline funcs.

* dwarf2.c (struct funcinfo): Delete nesting_level field.
(lookup_address_in_function_table): Delete code to set funcinfo
caller_func field.  Delete local curr_func.
(scan_unit_for_symbols): New locals nested_funcs, nested_funcs_size.
Delete code setting funcinfo nesting_level field.  Add code to set
funcinfo caller_func field.
This commit is contained in:
Jim Wilson 2005-09-22 19:50:27 +00:00
parent 82b19eb91f
commit c955f9cdcb
2 changed files with 53 additions and 23 deletions

View File

@ -1,3 +1,12 @@
2005-09-22 James E. Wilson <wilson@specifix.com>
* dwarf2.c (struct funcinfo): Delete nesting_level field.
(lookup_address_in_function_table): Delete code to set funcinfo
caller_func field. Delete local curr_func.
(scan_unit_for_symbols): New locals nested_funcs, nested_funcs_size.
Delete code setting funcinfo nesting_level field. Add code to set
funcinfo caller_func field.
2005-09-20 James E. Wilson <wilson@specifix.com>
* dwarf2.c (find_abstract_instance_name): Don't early exit when name

View File

@ -722,7 +722,6 @@ struct funcinfo
char *file; /* Source location file name */
int line; /* Source location line number */
int tag;
int nesting_level;
char *name;
struct arange arange;
asection *sec; /* Where the symbol is defined */
@ -1431,28 +1430,8 @@ lookup_address_in_function_table (struct comp_unit *unit,
if (best_fit)
{
struct funcinfo* curr_func = best_fit;
*functionname_ptr = best_fit->name;
*function_ptr = best_fit;
/* If we found a match and it is a function that was inlined,
traverse the function list looking for the function at the
next higher scope and save a pointer to it for future use.
Note that because of the way the DWARF info is generated, and
the way we build the function list, the first function at the
next higher level is the one we want. */
for (each_func = best_fit -> prev_func;
each_func && (curr_func->tag == DW_TAG_inlined_subroutine);
each_func = each_func->prev_func)
{
if (each_func->nesting_level < curr_func->nesting_level)
{
curr_func->caller_func = each_func;
curr_func = each_func;
}
}
return TRUE;
}
else
@ -1645,6 +1624,16 @@ scan_unit_for_symbols (struct comp_unit *unit)
bfd *abfd = unit->abfd;
bfd_byte *info_ptr = unit->first_child_die_ptr;
int nesting_level = 1;
struct funcinfo **nested_funcs;
int nested_funcs_size;
/* Maintain a stack of in-scope functions and inlined functions, which we
can use to set the caller_func field. */
nested_funcs_size = 32;
nested_funcs = bfd_malloc (nested_funcs_size * sizeof (struct funcinfo *));
if (nested_funcs == NULL)
return FALSE;
nested_funcs[nesting_level] = 0;
while (nesting_level)
{
@ -1671,6 +1660,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
(*_bfd_error_handler) (_("Dwarf Error: Could not find abbrev number %u."),
abbrev_number);
bfd_set_error (bfd_error_bad_value);
free (nested_funcs);
return FALSE;
}
@ -1682,9 +1672,17 @@ scan_unit_for_symbols (struct comp_unit *unit)
bfd_size_type amt = sizeof (struct funcinfo);
func = bfd_zalloc (abfd, amt);
func->tag = abbrev->tag;
func->nesting_level = nesting_level;
func->prev_func = unit->function_table;
unit->function_table = func;
if (func->tag == DW_TAG_inlined_subroutine)
for (i = nesting_level - 1; i >= 1; i--)
if (nested_funcs[i])
{
func->caller_func = nested_funcs[i];
break;
}
nested_funcs[nesting_level] = func;
}
else
{
@ -1698,6 +1696,9 @@ scan_unit_for_symbols (struct comp_unit *unit)
var->prev_var = unit->variable_table;
unit->variable_table = var;
}
/* No inline function in scope at this nesting level. */
nested_funcs[nesting_level] = 0;
}
for (i = 0; i < abbrev->num_attrs; ++i)
@ -1818,9 +1819,29 @@ scan_unit_for_symbols (struct comp_unit *unit)
}
if (abbrev->has_children)
nesting_level++;
{
nesting_level++;
if (nesting_level >= nested_funcs_size)
{
struct funcinfo **tmp;
nested_funcs_size *= 2;
tmp = bfd_realloc (nested_funcs,
(nested_funcs_size
* sizeof (struct funcinfo *)));
if (tmp == NULL)
{
free (nested_funcs);
return FALSE;
}
nested_funcs = tmp;
}
nested_funcs[nesting_level] = 0;
}
}
free (nested_funcs);
return TRUE;
}