static Dwarf_Die find_fundie_by_pc()

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, &current_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;
    }