static bool deep_first_search_by_pc()

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