Support decl cloning when seeing DW_AT_abstract_origin

* include/abg-ir.h ({var,function}_decl::clone): New method.
	* src/abg-dwarf-reader.cc (die_die_attribute): Add a flag to avoid
	looking through DW_AT_abstract_origin attribute here.
	(build_function_decl): Set the linkage name from
	DW_AT_linkage_name if it's not set yet.
	(build_ir_node_from_die): For DW_TAG_{variable,subprogram}, when
	we see DW_AT_abstract_origin, clone the decl they refer to.
	Also, avoid dropping the DIE on the floor just because it doesn't
	have die_is_artificial here.
	* src/abg-ir.cc ({var,function}_decl::clone): Implement this.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2014-05-20 18:22:14 +02:00
parent c91461a8c8
commit 4d0de72a85
3 changed files with 77 additions and 13 deletions

View File

@ -1312,6 +1312,9 @@ public:
elf_symbol_sptr
get_symbol() const;
var_decl_sptr
clone() const;
virtual size_t
get_hash() const;
@ -1572,6 +1575,9 @@ public:
binding
get_binding() const;
function_decl_sptr
clone() const;
virtual bool
operator==(const decl_base& o) const;

View File

@ -1998,14 +1998,28 @@ die_decl_file_attribute(Dwarf_Die* die)
/// @param result the DIE resulting from reading the attribute value.
/// This is set iff the function returns true.
///
/// @param look_through_abstract_origin if yes, the function looks
/// through the possible DW_AT_abstract_origin attribute all the way
/// down to the initial DIE that is cloned and look on that DIE to see
/// if it has the @p attr_name attribute.
///
/// @return true if the DIE @p die contains an attribute named @p
/// attr_name that is a DIE reference, false otherwise.
static bool
die_die_attribute(Dwarf_Die* die, unsigned attr_name, Dwarf_Die& result)
die_die_attribute(Dwarf_Die* die, unsigned attr_name, Dwarf_Die& result,
bool look_through_abstract_origin = true)
{
Dwarf_Attribute attr;
if (!dwarf_attr_integrate(die, attr_name, &attr))
return false;
if (look_through_abstract_origin)
{
if (!dwarf_attr_integrate(die, attr_name, &attr))
return false;
}
else
{
if (!dwarf_attr(die, attr_name, &attr))
return false;
}
return dwarf_formref_die(&attr, &result);
}
@ -4635,7 +4649,7 @@ build_function_decl(read_context& ctxt,
// Add the properties that might have been missing from the
// first declaration of the function. For now, it usually is
// the mangled name that goes missing in the first declarations.
if (!flinkage_name.empty())
if (!flinkage_name.empty() && result->get_linkage_name().empty())
result->set_linkage_name(flinkage_name);
}
else
@ -4930,7 +4944,10 @@ build_ir_node_from_die(read_context& ctxt,
case DW_TAG_variable:
{
Dwarf_Die spec_die;
if (die_die_attribute(die, DW_AT_specification, spec_die))
bool var_is_cloned = false;
if (die_die_attribute(die, DW_AT_specification, spec_die, false)
|| (var_is_cloned = die_die_attribute(die, DW_AT_abstract_origin,
spec_die, false)))
{
scope_decl_sptr scop = get_scope_for_die(ctxt, &spec_die,
called_from_public_decl,
@ -4945,11 +4962,13 @@ build_ir_node_from_die(read_context& ctxt,
{
var_decl_sptr m =
dynamic_pointer_cast<var_decl>(d);
if (var_is_cloned)
m = m->clone();
m = build_var_decl(ctxt, die, where_offset, m);
if (is_data_member(m))
{
set_member_is_static(m, true);
ctxt.die_decl_map()[dwarf_dieoffset(die)] = d;
ctxt.die_decl_map()[dwarf_dieoffset(die)] = m;
}
else
{
@ -4957,8 +4976,8 @@ build_ir_node_from_die(read_context& ctxt,
assert(has_scope(m));
ctxt.var_decls_to_re_add_to_tree().push_back(m);
}
assert(d->get_scope());
return d;
assert(m->get_scope());
return m;
}
}
}
@ -4978,13 +4997,16 @@ build_ir_node_from_die(read_context& ctxt,
{
Dwarf_Die spec_die;
scope_decl_sptr scop;
if (!die_is_public_decl(die)
|| die_is_artificial(die))
if (die_is_artificial(die))
break;
function_decl_sptr fn;
if (die_die_attribute(die, DW_AT_specification, spec_die)
|| die_die_attribute(die, DW_AT_abstract_origin, spec_die))
bool fn_is_clone = false;
if (die_die_attribute(die, DW_AT_specification,
spec_die, false)
|| (fn_is_clone =
die_die_attribute(die, DW_AT_abstract_origin,
spec_die, false)))
{
scop = get_scope_for_die(ctxt, &spec_die,
called_from_public_decl,
@ -5000,7 +5022,9 @@ build_ir_node_from_die(read_context& ctxt,
if (d)
{
fn = dynamic_pointer_cast<function_decl>(d);
ctxt.die_decl_map()[dwarf_dieoffset(die)] = d;
if (fn_is_clone)
fn = fn->clone();
ctxt.die_decl_map()[dwarf_dieoffset(die)] = fn;
}
}
}

View File

@ -3686,6 +3686,22 @@ elf_symbol_sptr
var_decl::get_symbol() const
{return priv_->symbol_;}
/// Create a new var_decl that is a clone of the current one.
///
/// @return the cloned var_decl.
var_decl_sptr
var_decl::clone() const
{
var_decl_sptr v(new var_decl(get_name(),
get_type(),
get_location(),
get_linkage_name(),
get_visibility(),
get_binding()));
v->set_symbol(get_symbol());
return v;
}
/// Setter of the scope of the current var_decl.
///
/// Note that the decl won't hold a reference on the scope. It's
@ -4350,6 +4366,24 @@ function_decl::append_parameters(std::vector<shared_ptr<parameter> >& parms)
get_type()->append_parameter(*i);
}
/// Create a new instance of function_decl that is a clone of the
/// current one.
///
/// @return the new clone.
function_decl_sptr
function_decl::clone() const
{
function_decl_sptr f(new function_decl(get_name(),
get_type(),
is_declared_inline(),
get_location(),
get_linkage_name(),
get_visibility(),
get_binding()));
f->set_symbol(get_symbol());
return f;
}
bool
function_decl::operator==(const decl_base& other) const
{