in src/backward.h [2954:3015]
static Dwarf_Die find_fundie_by_pc(dwarf_fileobject& fobj, Dwarf_Die parent_die, Dwarf_Addr pc, Dwarf_Die result)
{
Dwarf_Die current_die = 0;
Dwarf_Error error = DW_DLE_NE;
Dwarf_Debug dwarf = fobj.dwarf_handle.get();
if (dwarf_child(parent_die, ¤t_die, &error) != DW_DLV_OK) {
return NULL;
}
for (;;) {
Dwarf_Die sibling_die = 0;
Dwarf_Half tag_value;
dwarf_tag(current_die, &tag_value, &error);
switch (tag_value) {
case DW_TAG_subprogram:
case DW_TAG_inlined_subroutine:
if (die_has_pc(fobj, current_die, pc)) {
return current_die;
}
};
bool declaration = false;
Dwarf_Attribute attr_mem;
if (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, functions are
// not necessarily at the first level, but might be nested
// inside a namespace, structure, a function, an inlined
// function etc.
Dwarf_Die die_mem = 0;
Dwarf_Die indie = find_fundie_by_pc(fobj, current_die, pc, die_mem);
if (indie) {
result = die_mem;
return result;
}
}
int res = dwarf_siblingof(dwarf, current_die, &sibling_die, &error);
if (res == DW_DLV_ERROR) {
return NULL;
}
else if (res == DW_DLV_NO_ENTRY) {
break;
}
if (current_die != parent_die) {
dwarf_dealloc(dwarf, current_die, DW_DLA_DIE);
current_die = 0;
}
current_die = sibling_die;
}
return NULL;
}