in src/backward.h [2852:2947]
void operator()(Dwarf_Die die, std::vector<std::string>& ns)
{
Dwarf_Error error = DW_DLE_NE;
Dwarf_Half tag_value;
Dwarf_Attribute attr_mem;
Dwarf_Debug dwarf = fobj.dwarf_handle.get();
dwarf_tag(die, &tag_value, &error);
switch (tag_value) {
char* name;
case DW_TAG_subprogram:
if (!trace.source.function.empty())
break;
if (dwarf_diename(die, &name, &error) == DW_DLV_OK) {
trace.source.function = std::string(name);
dwarf_dealloc(dwarf, name, DW_DLA_STRING);
}
else {
// We don't have a function name in this DIE.
// Check if there is a referenced non-defining
// declaration.
trace.source.function = get_referenced_die_name(dwarf, die, DW_AT_abstract_origin, true);
if (trace.source.function.empty()) {
trace.source.function = get_referenced_die_name(dwarf, die, DW_AT_specification, true);
}
}
// Append the function parameters, if available
set_function_parameters(trace.source.function, ns, fobj, die);
// If the object function name is empty, it's possible that
// there is no dynamic symbol table (maybe the executable
// was stripped or not built with -rdynamic). See if we have
// a DWARF linkage name to use instead. We try both
// linkage_name and MIPS_linkage_name because the MIPS tag
// was the unofficial one until it was adopted in DWARF4.
// Old gcc versions generate MIPS_linkage_name
if (trace.object_function.empty()) {
details::demangler demangler;
if (dwarf_attr(die, DW_AT_linkage_name, &attr_mem, &error) != DW_DLV_OK) {
if (dwarf_attr(die, DW_AT_MIPS_linkage_name, &attr_mem, &error) != DW_DLV_OK) {
break;
}
}
char* linkage;
if (dwarf_formstring(attr_mem, &linkage, &error) == DW_DLV_OK) {
trace.object_function = demangler.demangle(linkage);
dwarf_dealloc(dwarf, linkage, DW_DLA_STRING);
}
dwarf_dealloc(dwarf, name, DW_DLA_ATTR);
}
break;
case DW_TAG_inlined_subroutine:
ResolvedTrace::SourceLoc sloc;
if (dwarf_diename(die, &name, &error) == DW_DLV_OK) {
sloc.function = std::string(name);
dwarf_dealloc(dwarf, name, DW_DLA_STRING);
}
else {
// We don't have a name for this inlined DIE, it could
// be that there is an abstract origin instead.
// Get the DW_AT_abstract_origin value, which is a
// reference to the source DIE and try to get its name
sloc.function = get_referenced_die_name(dwarf, die, DW_AT_abstract_origin, true);
}
set_function_parameters(sloc.function, ns, fobj, die);
std::string file = die_call_file(dwarf, die, cu_die);
if (!file.empty())
sloc.filename = file;
Dwarf_Unsigned number = 0;
if (dwarf_attr(die, DW_AT_call_line, &attr_mem, &error) == DW_DLV_OK) {
if (dwarf_formudata(attr_mem, &number, &error) == DW_DLV_OK) {
sloc.line = number;
}
dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR);
}
if (dwarf_attr(die, DW_AT_call_column, &attr_mem, &error) == DW_DLV_OK) {
if (dwarf_formudata(attr_mem, &number, &error) == DW_DLV_OK) {
sloc.col = number;
}
dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR);
}
trace.inliners.push_back(sloc);
break;
};
}