in src/backward.h [3018:3109]
static bool deep_first_search_by_pc(
dwarf_fileobject& fobj,
Dwarf_Die parent_die,
Dwarf_Addr pc,
std::vector<std::string>& ns,
CB cb)
{
Dwarf_Die current_die = 0;
Dwarf_Debug dwarf = fobj.dwarf_handle.get();
Dwarf_Error error = DW_DLE_NE;
if (dwarf_child(parent_die, ¤t_die, &error) != DW_DLV_OK) {
return false;
}
bool branch_has_pc = false;
bool has_namespace = false;
for (;;) {
Dwarf_Die sibling_die = 0;
Dwarf_Half tag;
if (dwarf_tag(current_die, &tag, &error) == DW_DLV_OK) {
if (tag == DW_TAG_namespace || tag == DW_TAG_class_type) {
char* ns_name = NULL;
if (dwarf_diename(current_die, &ns_name, &error) == DW_DLV_OK) {
if (ns_name) {
ns.push_back(std::string(ns_name));
}
else {
ns.push_back("<unknown>");
}
dwarf_dealloc(dwarf, ns_name, DW_DLA_STRING);
}
else {
ns.push_back("<unknown>");
}
has_namespace = true;
}
}
bool declaration = false;
Dwarf_Attribute attr_mem;
if (tag != DW_TAG_class_type &&
dwarf_attr(current_die, DW_AT_declaration, &attr_mem, &error) == DW_DLV_OK) {
Dwarf_Bool flag = 0;
if (dwarf_formflag(attr_mem, &flag, &error) == DW_DLV_OK) {
declaration = flag != 0;
}
dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR);
}
if (!declaration) {
// let's be curious and look deeper in the tree, function are
// not necessarily at the first level, but might be nested
// inside a namespace, structure, a function, an inlined
// function etc.
branch_has_pc = deep_first_search_by_pc(fobj, current_die, pc, ns, cb);
}
if (!branch_has_pc) {
branch_has_pc = die_has_pc(fobj, current_die, pc);
}
if (branch_has_pc) {
cb(current_die, ns);
}
int result = dwarf_siblingof(dwarf, current_die, &sibling_die, &error);
if (result == DW_DLV_ERROR) {
return false;
}
else if (result == DW_DLV_NO_ENTRY) {
break;
}
if (current_die != parent_die) {
dwarf_dealloc(dwarf, current_die, DW_DLA_DIE);
current_die = 0;
}
if (has_namespace) {
has_namespace = false;
ns.pop_back();
}
current_die = sibling_die;
}
if (has_namespace) {
ns.pop_back();
}
return branch_has_pc;
}