bool result = iterate_over_symbols (block, lookup_name, domain, data);
gdb_assert (result);
data.finish (block);
- return true;
+ return iteration_status::keep_going;
};
objfile->search (nullptr, &lookup_name, nullptr, callback,
}
}
- return true;
+ return iteration_status::keep_going;
};
/* In Ada, the symbol "search name" is a linkage name, whereas
}
}
- return true;
+ return iteration_status::keep_going;
};
objfile.search
/* Don't do this block twice. */
if (b != surrounding_static_block)
add_symbol_overload_list_block (func_name, b, overload_list);
- return true;
+ return iteration_status::keep_going;
};
/* Look through the partial symtabs for all symbols which
/* See cooked-index-entry.h. */
-bool
+iteration_status
cooked_index_entry::visit_defining_cus (per_cu_callback callback) const
{
if ((flags & IS_INLINED) == 0)
void force_set_language () const;
/* Type of callback used when visiting defining CUs. */
- using per_cu_callback = gdb::function_view<bool (dwarf2_per_cu *)>;
+ using per_cu_callback
+ = gdb::function_view<iteration_status (dwarf2_per_cu *)>;
/* Calls CALLBACK for each CU that "defines" this entry.
- If any call to CALLBACK returns false, this immediately returns
- false (skipping the remaining calls); otherwise returns true.
+ If any call to CALLBACK returns iteration_status::stop, this
+ immediately returns iteration_status::stop (skipping the remaining
+ calls); otherwise returns iteration_status::keep_going.
For most entries, there is a single defining CU, which is the
canonical outermost includer of the CU holding the entry. In the
such outermost includer -- if a subroutine is inlined in many
places, and then "dwz" is run, the IS_INLINED subroutine may be
defined in some CU that is included by many other CUs. */
- bool visit_defining_cus (per_cu_callback callback) const;
+ iteration_status visit_defining_cus (per_cu_callback callback) const;
/* The name as it appears in DWARF. This always points into one of
the mapped DWARF sections. Note that this may be the name or the
dwarf2_base_index_functions::expand_all_symtabs (objfile);
}
- bool search
+ iteration_status search
(struct objfile *objfile,
search_symtabs_file_matcher file_matcher,
const lookup_name_info *lookup_name,
entry->visit_defining_cus ([&] (dwarf2_per_cu *one_cu)
{
per_cus.push_back (one_cu);
- return true;
+ return iteration_status::keep_going;
});
/* Make sure the output is stable. */
std::sort (per_cus.begin (), per_cus.end (),
gdb_assert (it != cu_index_htab.cend ());
symtab->add_index_entry (name, (entry->flags & IS_STATIC) != 0,
kind, it->second);
- return true;
+ return iteration_status::keep_going;
});
}
}
{
}
- bool search (struct objfile *objfile,
- search_symtabs_file_matcher file_matcher,
- const lookup_name_info *lookup_name,
- search_symtabs_symbol_matcher symbol_matcher,
- compunit_symtab_iteration_callback compunit_callback,
- block_search_flags search_flags,
- domain_search_flags domain,
- search_symtabs_lang_matcher lang_matcher) override
+ iteration_status search (struct objfile *objfile,
+ search_symtabs_file_matcher file_matcher,
+ const lookup_name_info *lookup_name,
+ search_symtabs_symbol_matcher symbol_matcher,
+ compunit_symtab_iteration_callback compunit_callback,
+ block_search_flags search_flags,
+ domain_search_flags domain,
+ search_symtabs_lang_matcher lang_matcher) override
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
auto_bool_vector cus_to_skip;
|| per_objfile->get_compunit_symtab (per_cu.get ()) == nullptr)
continue;
- if (!search_one (per_cu.get (), per_objfile, cus_to_skip,
- compunit_callback, lang_matcher))
- return false;
+ if (search_one (per_cu.get (), per_objfile, cus_to_skip,
+ compunit_callback, lang_matcher)
+ == iteration_status::stop)
+ return iteration_status::stop;
}
- return true;
+
+ return iteration_status::keep_going;
}
struct symbol *find_symbol_by_address (struct objfile *objfile,
/* See read.h. */
-bool
+iteration_status
dwarf2_base_index_functions::search_one
(dwarf2_per_cu *per_cu,
dwarf2_per_objfile *per_objfile,
{
/* Already visited, or intentionally skipped. */
if (cus_to_skip.is_set (per_cu->index))
- return true;
+ return iteration_status::keep_going;
if (lang_matcher != nullptr)
{
per_cu->ensure_lang (per_objfile);
if (!per_cu->maybe_multi_language ()
&& !lang_matcher (per_cu->lang ()))
- return true;
+ return iteration_status::keep_going;
}
compunit_symtab *symtab
return compunit_callback (symtab);
}
- return true;
+ return iteration_status::keep_going;
}
/* If FILE_MATCHER is non-NULL, update CUS_TO_SKIP as appropriate
return cu->symbol_at_address (address);
}
-bool
+iteration_status
cooked_index_functions::search
(objfile *objfile,
search_symtabs_file_matcher file_matcher,
{
QUIT;
- if (!search_one (per_cu, per_objfile, cus_to_skip, compunit_callback,
- lang_matcher))
- return false;
+ if (search_one (per_cu, per_objfile, cus_to_skip, compunit_callback,
+ lang_matcher)
+ == iteration_status::stop)
+ return iteration_status::stop;
}
- return true;
+
+ return iteration_status::keep_going;
}
lookup_name_info lookup_name_without_params
else if (!symbol_matcher (full_name))
continue;
- bool check = entry->visit_defining_cus ([&] (dwarf2_per_cu *per_cu)
+ iteration_status status
+ = entry->visit_defining_cus ([&] (dwarf2_per_cu *per_cu)
{
return search_one (per_cu, per_objfile, cus_to_skip,
compunit_callback, nullptr);
});
- if (!check)
- return false;
+
+ if (status == iteration_status::stop)
+ return iteration_status::stop;
}
}
- return true;
+ return iteration_status::keep_going;
}
/* Start reading .debug_info using the indexer. */
/* See read.h. */
-bool
+iteration_status
dwarf2_per_cu::recursively_visit_cus (per_cu_callback callback)
{
if (including_cus.empty ())
return callback (this);
+
for (dwarf2_per_cu *iter : including_cus)
- if (!iter->recursively_visit_cus (callback))
- return false;
- return true;
+ if (iter->recursively_visit_cus (callback) == iteration_status::stop)
+ return iteration_status::stop;
+
+ return iteration_status::keep_going;
}
/* See read.h. */
#include "gdbsupport/cxx-thread.h"
#include "gdbsupport/gdb_obstack.h"
#include "gdbsupport/function-view.h"
+#include "gdbsupport/iteration-status.h"
#include "gdbsupport/packed.h"
/* Hold 'maintenance (set|show) dwarf' commands. */
}
/* Type of callback used when visiting defining CUs. */
- using per_cu_callback = gdb::function_view<bool (dwarf2_per_cu *)>;
+ using per_cu_callback
+ = gdb::function_view<iteration_status (dwarf2_per_cu *)>;
/* Calls CALLBACK for each CU that is the outermost includer of
ONE_CU. If ONE_CU has no includers, it calls CALLBACK on ONE_CU.
- If any call to CALLBACK returns false, this immediately returns
- false (skipping the remaining calls); otherwise returns true. */
- bool recursively_visit_cus (per_cu_callback callback);
+ If any call to CALLBACK returns iteration_status::stop, this
+ immediately returns iteration_status::stop (skipping the remaining
+ calls); otherwise returns iteration_status::keep_going. */
+ iteration_status recursively_visit_cus (per_cu_callback callback);
/* Return a canonical outermost CU corresponding to this CU. If
this CU is standalone (not included by other CUs), then this
/* If CUS_TO_SKIP does not include the CU's index and the CU's language
matches LANG_MATCHER, expand the CU and call COMPUNIT_CALLBACK (if
provided) on it. */
- bool search_one (dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile,
- auto_bool_vector &cus_to_skip,
- compunit_symtab_iteration_callback compunit_callback,
- search_symtabs_lang_matcher lang_matcher);
+ iteration_status search_one
+ (dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile,
+ auto_bool_vector &cus_to_skip,
+ compunit_symtab_iteration_callback compunit_callback,
+ search_symtabs_lang_matcher lang_matcher);
};
/* Return pointer to string at .debug_str offset STR_OFFSET. */
/* See expanded-symbol.h. */
-bool
+iteration_status
expanded_symbols_functions::search
(objfile *objfile,
search_symtabs_file_matcher file_matcher,
consult lookup_name and symbol_matcher (if any). This should be
okay since i) all symtabs are already expanded and ii) callbacks
iterate over matching symbols themselves. */
- if (compunit_callback != nullptr && !compunit_callback (cu))
- return false;
+ if (compunit_callback != nullptr
+ && compunit_callback (cu) == iteration_status::stop)
+ return iteration_status::stop;
}
- return true;
+
+ return iteration_status::keep_going;
}
/* See expanded-symbol.h. */
{
}
- bool search (objfile *objfile,
- search_symtabs_file_matcher file_matcher,
- const lookup_name_info *lookup_name,
- search_symtabs_symbol_matcher symbol_matcher,
- compunit_symtab_iteration_callback compunit_callback,
- block_search_flags search_flags, domain_search_flags domain,
- search_symtabs_lang_matcher lang_matcher) override;
+ iteration_status search (objfile *objfile,
+ search_symtabs_file_matcher file_matcher,
+ const lookup_name_info *lookup_name,
+ search_symtabs_symbol_matcher symbol_matcher,
+ compunit_symtab_iteration_callback compunit_callback,
+ block_search_flags search_flags,
+ domain_search_flags domain,
+ search_symtabs_lang_matcher lang_matcher) override;
compunit_symtab *find_pc_sect_compunit_symtab
(objfile *objfile, bound_minimal_symbol msymbol, CORE_ADDR pc,
}
}
- return true;
+ return iteration_status::keep_going;
};
objfile.search (nullptr, &lookup_name, nullptr, expand_callback,
{
if (symtab_table.insert (symtab).second)
symtabs.push_back (symtab);
- return false;
+ return iteration_status::keep_going;
};
/* Find that file's data. */
Then, this calls iterate_over_some_symtabs (or equivalent) over
all newly-created symbol tables, passing CALLBACK to it.
The result of this call is returned. */
- bool map_symtabs_matching_filename
+ iteration_status map_symtabs_matching_filename
(const char *name, const char *real_path,
- gdb::function_view<bool (symtab *)> callback);
+ gdb::function_view<iteration_status (symtab *)> callback);
/* Check to see if the symbol is defined in a "partial" symbol table
of this objfile. BLOCK_INDEX should be either GLOBAL_BLOCK or
void expand_symtabs_with_fullname (const char *fullname);
/* See quick_symbol_functions. */
- bool search
- (search_symtabs_file_matcher file_matcher,
- const lookup_name_info *lookup_name,
- search_symtabs_symbol_matcher symbol_matcher,
- compunit_symtab_iteration_callback compunit_callback,
- block_search_flags search_flags,
- domain_search_flags domain,
- search_symtabs_lang_matcher lang_matcher = nullptr);
+ iteration_status search (search_symtabs_file_matcher file_matcher,
+ const lookup_name_info *lookup_name,
+ search_symtabs_symbol_matcher symbol_matcher,
+ compunit_symtab_iteration_callback compunit_callback,
+ block_search_flags search_flags,
+ domain_search_flags domain,
+ search_symtabs_lang_matcher lang_matcher = nullptr);
/* See quick_symbol_functions. */
struct compunit_symtab *
/* Skip included compunits to prevent including compunits from
being searched twice. */
if (cust->user != nullptr)
- return true;
+ return iteration_status::keep_going;
const struct blockvector *bv = cust->blockvector ();
const struct block *block = bv->static_block ();
if (sym_obj == nullptr
|| PyList_Append (return_list.get (),
sym_obj.get ()) == -1)
- return false;
+ return iteration_status::stop;
}
}
- return true;
+ return iteration_status::keep_going;
};
- if (!objfile.search (nullptr, &lookup_name, nullptr, callback,
- SEARCH_STATIC_BLOCK, flags))
- return nullptr;
+ /* The only reason why the iteration would stop is if an error was
+ encountered during the callback execution. */
+ if (objfile.search (nullptr, &lookup_name, nullptr, callback,
+ SEARCH_STATIC_BLOCK, flags)
+ == iteration_status::stop)
+ {
+ gdb_assert (PyErr_Occurred ());
+ return nullptr;
+ }
}
}
catch (const gdb_exception &except)
#define GDB_QUICK_SYMBOL_H
#include "symtab.h"
+#include "gdbsupport/iteration-status.h"
/* Like block_enum, but used as flags to pass to lookup functions. */
= gdb::function_view<bool (enum language lang)>;
/* Callback for quick_symbol_functions::search to be called when a
- compunit_symtab matches (perhaps expanding it first). If this
- returns true, more compunit_symtabs are checked; if it returns false,
- iteration stops. */
+ compunit_symtab matches (perhaps expanding it first). */
using compunit_symtab_iteration_callback
- = gdb::function_view<bool (compunit_symtab *symtab)>;
+ = gdb::function_view<iteration_status (compunit_symtab *symtab)>;
/* The "quick" symbol functions exist so that symbol readers can
avoiding an initial read of all the symbols. For example, symbol
Then (regardless of whether the symbol table was already
expanded, or just expanded in response to this search),
- COMPUNIT_CALLBACK is called. If COMPUNIT_CALLBACK returns false,
- execution stops and this method returns false. Otherwise, more
- files are considered. This method returns true if all calls to
- COMPUNIT_CALLBACK return true. */
- virtual bool search
+ COMPUNIT_CALLBACK is called. If COMPUNIT_CALLBACK returns
+ iteration_status::stop, execution stops and this method returns
+ iteration_status::stop. Otherwise, more files are considered. This
+ method returns iteration_status::keep_going if all calls to
+ COMPUNIT_CALLBACK return iteration_status::keep_going. */
+ virtual iteration_status search
(struct objfile *objfile,
search_symtabs_file_matcher file_matcher,
const lookup_name_info *lookup_name,
CUST indicates which compunit symtab to search. Each symtab within
the specified compunit symtab is also searched. */
-static bool
-iterate_over_one_compunit_symtab (const char *base_name,
- const char *name,
- const char *real_path,
- compunit_symtab *cust,
- gdb::function_view<bool (symtab *)> callback)
+static iteration_status
+iterate_over_one_compunit_symtab
+ (const char *base_name, const char *name, const char *real_path,
+ compunit_symtab *cust,
+ gdb::function_view<iteration_status (symtab *)> callback)
{
for (symtab *s : cust->filetabs ())
{
if (compare_filenames_for_search (s->filename (), name))
{
- if (callback (s))
- return true;
+ if (callback (s) == iteration_status::stop)
+ return iteration_status::stop;
continue;
}
if (compare_filenames_for_search (symtab_to_fullname (s), name))
{
- if (callback (s))
- return true;
+ if (callback (s) == iteration_status::stop)
+ return iteration_status::stop;
continue;
}
fullname = fullname_real_path.get ();
if (FILENAME_CMP (real_path, fullname) == 0)
{
- if (callback (s))
- return true;
+ if (callback (s) == iteration_status::stop)
+ return iteration_status::stop;
continue;
}
}
}
for (compunit_symtab *iter : cust->includes)
- if (iterate_over_one_compunit_symtab (base_name, name, real_path,
- iter, callback))
- return true;
+ if (iterate_over_one_compunit_symtab (base_name, name, real_path, iter,
+ callback)
+ == iteration_status::stop)
+ return iteration_status::stop;
- return false;
+ return iteration_status::keep_going;
}
-bool
+iteration_status
objfile::map_symtabs_matching_filename
(const char *name, const char *real_path,
- gdb::function_view<bool (symtab *)> callback)
+ gdb::function_view<iteration_status (symtab *)> callback)
{
if (debug_symfile)
gdb_printf (gdb_stdlog,
real_path ? real_path : NULL,
host_address_to_string (&callback));
- bool retval = false;
const char *name_basename = lbasename (name);
auto match_one_filename = [&] (const char *filename, bool basenames)
/* Skip included compunits, as they are searched by
iterate_over_one_compunit_symtab. */
if (symtab->user != nullptr)
- return true;
+ return iteration_status::keep_going;
- /* CALLBACK returns false to keep going and true to continue, so
- we have to invert the result here, for search. */
- return !iterate_over_one_compunit_symtab (name_basename, name, real_path,
- symtab, callback);
+ /* iterate_over_one_compunit_symtab returns true to stop,
+ convert to iteration_status. */
+ return iterate_over_one_compunit_symtab (name_basename, name, real_path,
+ symtab, callback);
};
+ iteration_status retval = iteration_status::keep_going;
+
for (const auto &iter : qf)
{
- if (!iter->search (this, match_one_filename, nullptr, nullptr,
- compunit_callback,
- SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
- SEARCH_ALL_DOMAINS))
+ if (iter->search (this, match_one_filename, nullptr, nullptr,
+ compunit_callback,
+ SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
+ SEARCH_ALL_DOMAINS)
+ == iteration_status::stop)
{
- retval = true;
+ retval = iteration_status::stop;
break;
}
}
if (debug_symfile)
gdb_printf (gdb_stdlog,
- "qf->map_symtabs_matching_filename (...) = %d\n",
- retval);
+ "qf->map_symtabs_matching_filename (...) = %s\n",
+ iteration_status_str (retval));
return retval;
}
{
retval = stab;
/* Found it. */
- return false;
+ return iteration_status::stop;
}
if (with_opaque != nullptr)
retval = stab;
/* Keep looking through other psymtabs. */
- return true;
+ return iteration_status::keep_going;
};
for (const auto &iter : qf)
{
- if (!iter->search (this, nullptr, &name, nullptr, search_one_symtab,
- kind == GLOBAL_BLOCK
- ? SEARCH_GLOBAL_BLOCK
- : SEARCH_STATIC_BLOCK,
- domain))
+ if (iter->search (this, nullptr, &name, nullptr, search_one_symtab,
+ kind == GLOBAL_BLOCK
+ ? SEARCH_GLOBAL_BLOCK
+ : SEARCH_STATIC_BLOCK,
+ domain)
+ == iteration_status::stop)
break;
}
SEARCH_ALL_DOMAINS);
}
-bool
+iteration_status
objfile::search (search_symtabs_file_matcher file_matcher,
const lookup_name_info *lookup_name,
search_symtabs_symbol_matcher symbol_matcher,
domain_name (domain).c_str ());
for (const auto &iter : qf)
- if (!iter->search (this, file_matcher, lookup_name, symbol_matcher,
- compunit_callback, search_flags, domain, lang_matcher))
- return false;
- return true;
+ if (iter->search (this, file_matcher, lookup_name, symbol_matcher,
+ compunit_callback, search_flags, domain, lang_matcher)
+ == iteration_status::stop)
+ return iteration_status::stop;
+
+ return iteration_status::keep_going;
}
struct compunit_symtab *
void
iterate_over_symtabs (program_space *pspace, const char *name,
- gdb::function_view<bool (symtab *)> callback)
+ gdb::function_view<iteration_status (symtab *)> callback)
{
gdb::unique_xmalloc_ptr<char> real_path;
for (objfile &objfile : pspace->objfiles ())
if (objfile.map_symtabs_matching_filename (name, real_path.get (),
- callback))
+ callback)
+ == iteration_status::stop)
return;
}
iterate_over_symtabs (pspace, name, [&] (symtab *symtab)
{
result = symtab;
- return true;
+ return iteration_status::stop;
});
return result;
{
const struct blockvector *bv = symtab->blockvector ();
const struct block *block = bv->block (block_index);
- /* If the accumulator finds a best symbol, end the search by
- returning false; otherwise keep going by returning true. */
- return !accum.search (symtab, block, lookup_name, domain);
+ /* End the search if the accumulator finds a best symbol. */
+ if (accum.search (symtab, block, lookup_name, domain))
+ return iteration_status::stop;
+
+ return iteration_status::keep_going;
};
objfile->search (nullptr, &lookup_name, nullptr, searcher,
add_symtab_completions (symtab,
tracker, mode, lookup_name,
sym_text, word, code);
- return true;
+ return iteration_status::keep_going;
},
SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
SEARCH_ALL_DOMAINS);
add_symtab_completions (s->compunit (),
tracker, mode, lookup_name,
sym_text, word, TYPE_CODE_UNDEF);
- return false;
+ return iteration_status::keep_going;
});
}
#include "gdbsupport/gdb_regex.h"
#include "gdbsupport/enum-flags.h"
#include "gdbsupport/function-view.h"
+#include "gdbsupport/iteration-status.h"
#include <optional>
#include <string_view>
#include "gdbsupport/next-iterator.h"
symtab filename will also work.
Call CALLBACK with each symtab that is found. If CALLBACK returns
- true, the search stops. */
+ iteration_status::stop, the search stops. */
-void iterate_over_symtabs (program_space *pspace, const char *name,
- gdb::function_view<bool (symtab *)> callback);
+void iterate_over_symtabs
+ (program_space *pspace, const char *name,
+ gdb::function_view<iteration_status (symtab *)> callback);
std::vector<const linetable_entry *> find_linetable_entries_for_symtab_line
(struct symtab *symtab, int line, const linetable_entry **best_entry);
--- /dev/null
+/* Copyright (C) 2026 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDBSUPPORT_ITERATION_STATUS_H
+#define GDBSUPPORT_ITERATION_STATUS_H
+
+/* Return type for iteration callbacks.
+
+ Using an enum makes it clear at each call site whether the callback wants to
+ stop or continue, unlike a plain bool where the convention can change between
+ APIs. */
+
+enum class iteration_status
+{
+ keep_going,
+ stop,
+};
+
+constexpr const char *
+iteration_status_str (iteration_status status)
+{
+ switch (status)
+ {
+ case iteration_status::keep_going:
+ return "keep_going";
+
+ case iteration_status::stop:
+ return "stop";
+ }
+
+ gdb_assert_not_reached ("invalid iteration_status value");
+}
+
+#endif /* GDBSUPPORT_ITERATION_STATUS_H */