static bfd_uint64_t
read_address (struct comp_unit *unit, bfd_byte *buf)
{
- switch (unit->addr_size)
+ int signed_vma = get_elf_backend_data (unit->abfd)->sign_extend_vma;
+
+ if (signed_vma)
{
- case 8:
- return bfd_get_64 (unit->abfd, buf);
- case 4:
- return bfd_get_32 (unit->abfd, buf);
- case 2:
- return bfd_get_16 (unit->abfd, buf);
- default:
- abort ();
+ switch (unit->addr_size)
+ {
+ case 8:
+ return bfd_get_signed_64 (unit->abfd, buf);
+ case 4:
+ return bfd_get_signed_32 (unit->abfd, buf);
+ case 2:
+ return bfd_get_signed_16 (unit->abfd, buf);
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ switch (unit->addr_size)
+ {
+ case 8:
+ return bfd_get_64 (unit->abfd, buf);
+ case 4:
+ return bfd_get_32 (unit->abfd, buf);
+ case 2:
+ return bfd_get_16 (unit->abfd, buf);
+ default:
+ abort ();
+ }
}
}
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 */
int line;
int tag;
char *name;
+ bfd_vma addr;
/* Where the symbol is defined */
asection *sec;
/* Is this a stack variable? */
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
static bfd_boolean
lookup_symbol_in_variable_table (struct comp_unit *unit,
asymbol *sym,
+ bfd_vma addr,
const char **filename_ptr,
unsigned int *linenumber_ptr)
{
for (each = unit->variable_table; each; each = each->prev_var)
if (each->stack == 0
+ && each->file != NULL
+ && each->name != NULL
+ && each->addr == addr
&& (!each->sec || each->sec == sec)
&& strcmp (name, each->name) == 0)
break;
}
else
{
- for (i = 0; i < abbrev->num_attrs && !name; ++i)
+ for (i = 0; i < abbrev->num_attrs; ++i)
{
info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
switch (attr.name)
{
case DW_AT_name:
- name = attr.u.str;
+ /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name. */
+ if (name == NULL)
+ name = attr.u.str;
break;
case DW_AT_specification:
name = find_abstract_instance_name (unit, attr.u.val);
break;
+ case DW_AT_MIPS_linkage_name:
+ name = attr.u.str;
+ break;
default:
break;
}
bfd_vma low_pc;
bfd_vma high_pc;
- if (unit->offset_size == 4)
+ if (unit->addr_size == 4)
{
low_pc = read_4_bytes (unit->abfd, ranges_ptr);
ranges_ptr += 4;
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)
{
(*_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;
}
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
{
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)
break;
case DW_AT_location:
- if (var->stack)
+ switch (attr.form)
{
- switch (attr.form)
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ if (*attr.u.blk->data == DW_OP_addr)
{
- case DW_FORM_block:
- case DW_FORM_block1:
- case DW_FORM_block2:
- case DW_FORM_block4:
- if (*attr.u.blk->data == DW_OP_addr)
- var->stack = 0;
- break;
-
- default:
- break;
+ var->stack = 0;
+
+ /* Verify that DW_OP_addr is the only opcode in the
+ location, in which case the block size will be 1
+ plus the address size. */
+ /* ??? For TLS variables, gcc can emit
+ DW_OP_addr <addr> DW_OP_GNU_push_tls_address
+ which we don't handle here yet. */
+ if (attr.u.blk->size == unit->addr_size + 1U)
+ var->addr = bfd_get (unit->addr_size * 8,
+ unit->abfd,
+ attr.u.blk->data + 1);
}
+ break;
+
+ default:
+ break;
}
break;
}
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;
}
filename_ptr,
linenumber_ptr);
else
- return lookup_symbol_in_variable_table (unit, sym, filename_ptr,
+ return lookup_symbol_in_variable_table (unit, sym, addr,
+ filename_ptr,
linenumber_ptr);
}
stash = *pinfo;
addr = offset;
if (section->output_section)
- addr += section->output_section->vma + section->output_offset;
+ addr += section->output_section->lma + section->output_offset;
else
- addr += section->vma;
+ addr += section->lma;
*filename_ptr = NULL;
*functionname_ptr = NULL;
*linenumber_ptr = 0;
addr = symbol->value;
if (section->output_section)
- addr += section->output_section->vma + section->output_offset;
+ addr += section->output_section->lma + section->output_offset;
else
- addr += section->vma;
+ addr += section->lma;
*filename_ptr = NULL;
stash = *pinfo;