gdb: make iterate_over_objfiles_in_search_order methods of program_space and solib_ops

Change the "iterate over objfiles in search order" operation from a
gdbarch method to methods on both program_space and solib_ops.

The first motivation for this is that I want to encapsulate solib-svr4's
data into svr4_solib_ops (in a subsequent series), instead of it being
in a separate structure (svr4_info).  It is awkward to do so as long as
there are entry points that aren't the public solib_ops interface.

The second motivation is my project of making it able to have multiple
solib_ops per program space (which should be the subject of said
subsequent series), to better support heterogenousa systems (like ROCm,
with CPU and GPU in the same inferior).  When we have this, when stopped
in GPU code, it won't make sense to ask the host's architecture to do
the iteration, as the logic could be different for the GPU architecture.
Instead, program_space::iterate_over_objfiles_in_search_order will be
responsible to delegate to the various solib_ops using a logic that is
yet to be determined.

I included this patch in this series (rather than the following one)
so that svr4_solib_ops::iterate_over_objfiles_in_search_order can access
svr4_solib_ops::default_debug_base, introduced in a later patch in this
series.

default_iterate_over_objfiles_in_search_order becomes the default
implementation of solib_ops::iterate_over_objfiles_in_search_order.

As far as I know, all architectures using
svr4_iterate_over_objfiles_in_search_order also use solib_ops_svr4, so I
don't expect this patch to cause behavior changes.

Change-Id: I71f8a800b8ce782ab973af2f2eb5fcfe4e06ec76
Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
This commit is contained in:
Simon Marchi
2025-07-15 11:52:32 -04:00
parent 77c87c12b3
commit fbb487b451
20 changed files with 139 additions and 164 deletions

View File

@@ -4901,9 +4901,8 @@ ada_lookup_simple_minsym (const char *name, struct objfile *objfile)
symbol_name_matcher_ftype *match_name
= ada_get_symbol_name_matcher (lookup_name);
gdbarch_iterate_over_objfiles_in_search_order
(objfile != NULL ? objfile->arch () : current_inferior ()->arch (),
[&result, lookup_name, match_name] (struct objfile *obj)
current_program_space->iterate_over_objfiles_in_search_order
([&result, lookup_name, match_name] (struct objfile *obj)
{
for (minimal_symbol *msymbol : obj->msymbols ())
{

View File

@@ -1472,9 +1472,8 @@ add_symbol_overload_list_qualified (const char *func_name,
? selected_block->objfile ()
: nullptr);
gdbarch_iterate_over_objfiles_in_search_order
(current_objfile ? current_objfile->arch () : current_inferior ()->arch (),
[func_name, surrounding_static_block, &overload_list]
current_program_space->iterate_over_objfiles_in_search_order
([func_name, surrounding_static_block, &overload_list]
(struct objfile *obj)
{
/* Look through the partial symtabs for all symbols which

View File

@@ -776,9 +776,8 @@ elf_gnu_ifunc_resolve_by_cache (const char *name, CORE_ADDR *addr_p)
To search other namespaces, we would need to provide context, e.g. in
form of an objfile in that namespace. */
gdbarch_iterate_over_objfiles_in_search_order
(current_inferior ()->arch (),
[name, &addr_p, &found] (struct objfile *objfile)
current_program_space->iterate_over_objfiles_in_search_order
([name, &addr_p, &found] (struct objfile *objfile)
{
htab_t htab;
elf_gnu_ifunc_cache *entry_p;
@@ -830,9 +829,8 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p)
To search other namespaces, we would need to provide context, e.g. in
form of an objfile in that namespace. */
gdbarch_iterate_over_objfiles_in_search_order
(current_inferior ()->arch (),
[name, name_got_plt, &addr_p, &found] (struct objfile *objfile)
current_program_space->iterate_over_objfiles_in_search_order
([name, name_got_plt, &addr_p, &found] (struct objfile *objfile)
{
bfd *obfd = objfile->obfd.get ();
struct gdbarch *gdbarch = objfile->arch ();

View File

@@ -445,9 +445,8 @@ language_defn::read_var_value (struct symbol *var,
struct obj_section *obj_section;
bound_minimal_symbol bmsym;
gdbarch_iterate_over_objfiles_in_search_order
(var->arch (),
[var, &bmsym] (objfile *objfile)
current_program_space->iterate_over_objfiles_in_search_order
([var, &bmsym] (objfile *objfile)
{
bmsym = lookup_minimal_symbol (current_program_space,
var->linkage_name (), objfile);

View File

@@ -240,7 +240,6 @@ struct gdbarch
gdbarch_gen_return_address_ftype *gen_return_address = default_gen_return_address;
gdbarch_info_proc_ftype *info_proc = nullptr;
gdbarch_core_info_proc_ftype *core_info_proc = nullptr;
gdbarch_iterate_over_objfiles_in_search_order_ftype *iterate_over_objfiles_in_search_order = default_iterate_over_objfiles_in_search_order;
struct ravenscar_arch_ops * ravenscar_ops = NULL;
gdbarch_insn_is_call_ftype *insn_is_call = default_insn_is_call;
gdbarch_insn_is_ret_ftype *insn_is_ret = default_insn_is_ret;
@@ -513,7 +512,6 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of gen_return_address, invalid_p == 0. */
/* Skip verify of info_proc, has predicate. */
/* Skip verify of core_info_proc, has predicate. */
/* Skip verify of iterate_over_objfiles_in_search_order, invalid_p == 0. */
/* Skip verify of ravenscar_ops, invalid_p == 0. */
/* Skip verify of insn_is_call, invalid_p == 0. */
/* Skip verify of insn_is_ret, invalid_p == 0. */
@@ -1337,9 +1335,6 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
gdb_printf (file,
"gdbarch_dump: core_info_proc = <%s>\n",
host_address_to_string (gdbarch->core_info_proc));
gdb_printf (file,
"gdbarch_dump: iterate_over_objfiles_in_search_order = <%s>\n",
host_address_to_string (gdbarch->iterate_over_objfiles_in_search_order));
gdb_printf (file,
"gdbarch_dump: ravenscar_ops = %s\n",
host_address_to_string (gdbarch->ravenscar_ops));
@@ -5171,23 +5166,6 @@ set_gdbarch_core_info_proc (struct gdbarch *gdbarch,
gdbarch->core_info_proc = core_info_proc;
}
void
gdbarch_iterate_over_objfiles_in_search_order (struct gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb, struct objfile *current_objfile)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->iterate_over_objfiles_in_search_order != NULL);
if (gdbarch_debug >= 2)
gdb_printf (gdb_stdlog, "gdbarch_iterate_over_objfiles_in_search_order called\n");
gdbarch->iterate_over_objfiles_in_search_order (gdbarch, cb, current_objfile);
}
void
set_gdbarch_iterate_over_objfiles_in_search_order (struct gdbarch *gdbarch,
gdbarch_iterate_over_objfiles_in_search_order_ftype iterate_over_objfiles_in_search_order)
{
gdbarch->iterate_over_objfiles_in_search_order = iterate_over_objfiles_in_search_order;
}
struct ravenscar_arch_ops *
gdbarch_ravenscar_ops (struct gdbarch *gdbarch)
{

View File

@@ -1634,19 +1634,6 @@ typedef void (gdbarch_core_info_proc_ftype) (struct gdbarch *gdbarch, const char
extern void gdbarch_core_info_proc (struct gdbarch *gdbarch, const char *args, enum info_proc_what what);
extern void set_gdbarch_core_info_proc (struct gdbarch *gdbarch, gdbarch_core_info_proc_ftype *core_info_proc);
/* Iterate over all objfiles in the order that makes the most sense
for the architecture to make global symbol searches.
CB is a callback function passed an objfile to be searched. The iteration stops
if this function returns nonzero.
If not NULL, CURRENT_OBJFILE corresponds to the objfile being
inspected when the symbol search was requested. */
typedef void (gdbarch_iterate_over_objfiles_in_search_order_ftype) (struct gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb, struct objfile *current_objfile);
extern void gdbarch_iterate_over_objfiles_in_search_order (struct gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb, struct objfile *current_objfile);
extern void set_gdbarch_iterate_over_objfiles_in_search_order (struct gdbarch *gdbarch, gdbarch_iterate_over_objfiles_in_search_order_ftype *iterate_over_objfiles_in_search_order);
/* Ravenscar arch-dependent ops. */
extern struct ravenscar_arch_ops * gdbarch_ravenscar_ops (struct gdbarch *gdbarch);

View File

@@ -75,12 +75,6 @@ struct gdbarch_tdep_base
using gdbarch_tdep_up = std::unique_ptr<gdbarch_tdep_base>;
/* Callback type for the 'iterate_over_objfiles_in_search_order'
gdbarch method. */
using iterate_over_objfiles_in_search_order_cb_ftype
= gdb::function_view<bool(objfile *)>;
/* Callback type for regset section iterators. The callback usually
invokes the REGSET's supply or collect method, to which it must
pass a buffer - for collects this buffer will need to be created using

View File

@@ -2562,27 +2562,6 @@ one for live targets.
predicate=True,
)
Method(
comment="""
Iterate over all objfiles in the order that makes the most sense
for the architecture to make global symbol searches.
CB is a callback function passed an objfile to be searched. The iteration stops
if this function returns nonzero.
If not NULL, CURRENT_OBJFILE corresponds to the objfile being
inspected when the symbol search was requested.
""",
type="void",
name="iterate_over_objfiles_in_search_order",
params=[
("iterate_over_objfiles_in_search_order_cb_ftype", "cb"),
("struct objfile *", "current_objfile"),
],
predefault="default_iterate_over_objfiles_in_search_order",
invalid=False,
)
Value(
comment="""
Ravenscar arch-dependent ops.

View File

@@ -1154,24 +1154,6 @@ shared_objfile_contains_address_p (struct program_space *pspace,
return false;
}
/* The default implementation for the "iterate_over_objfiles_in_search_order"
gdbarch method. It is equivalent to use the objfiles iterable,
searching the objfiles in the order they are stored internally,
ignoring CURRENT_OBJFILE.
On most platforms, it should be close enough to doing the best
we can without some knowledge specific to the architecture. */
void
default_iterate_over_objfiles_in_search_order
(gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile)
{
for (objfile *objfile : current_program_space->objfiles ())
if (cb (objfile))
return;
}
/* See objfiles.h. */
const char *

View File

@@ -1010,10 +1010,6 @@ in_plt_section (CORE_ADDR pc)
extern scoped_restore_tmpl<int> inhibit_section_map_updates
(struct program_space *pspace);
extern void default_iterate_over_objfiles_in_search_order
(gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile);
/* Reset the per-BFD storage area on OBJ. */
void set_objfile_per_bfd (struct objfile *obj);

View File

@@ -145,6 +145,21 @@ program_space::free_all_objfiles ()
/* See progspace.h. */
void
program_space::iterate_over_objfiles_in_search_order
(iterate_over_objfiles_in_search_order_cb_ftype cb, objfile *current_objfile)
{
if (m_solib_ops != nullptr)
return m_solib_ops->iterate_over_objfiles_in_search_order
(cb, current_objfile);
for (const auto objfile : this->objfiles ())
if (cb (objfile))
return;
}
/* See progspace.h. */
void
program_space::add_objfile (std::unique_ptr<objfile> &&objfile,
struct objfile *before)

View File

@@ -212,6 +212,18 @@ struct program_space
(objfiles_range (objfiles_iterator (m_objfiles_list.begin ())));
}
/* Iterate over all objfiles of the program space in the order that makes the
most sense to make global symbol searches.
CB is a callback function passed an objfile to be searched. The iteration stops
if this function returns true.
If not nullptr, CURRENT_OBJFILE corresponds to the objfile being
inspected when the symbol search was requested. */
void iterate_over_objfiles_in_search_order
(iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile);
/* Add OBJFILE to the list of objfiles, putting it just before
BEFORE. If BEFORE is nullptr, it will go at the end of the
list. */

View File

@@ -619,9 +619,8 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
struct objfile *objfile = nullptr;
if (by_build_id)
gdbarch_iterate_over_objfiles_in_search_order
(current_inferior ()->arch (),
[&objfile, name] (struct objfile *obj)
current_program_space->iterate_over_objfiles_in_search_order
([&objfile, name] (struct objfile *obj)
{
/* Don't return separate debug files. */
if (obj->separate_debug_objfile_backlink != nullptr)
@@ -642,9 +641,8 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
return 1;
}, gdbpy_current_objfile);
else
gdbarch_iterate_over_objfiles_in_search_order
(current_inferior ()->arch (),
[&objfile, name] (struct objfile *obj)
current_program_space->iterate_over_objfiles_in_search_order
([&objfile, name] (struct objfile *obj)
{
/* Don't return separate debug files. */
if (obj->separate_debug_objfile_backlink != nullptr)

View File

@@ -211,6 +211,14 @@ struct rocm_solib_ops : public solib_ops
std::vector<const solib *> get_solibs_in_ns (int nsid) const override
{ return m_host_ops->get_solibs_in_ns (nsid); }
void iterate_over_objfiles_in_search_order
(iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile) const override
{
return m_host_ops->iterate_over_objfiles_in_search_order
(cb, current_objfile);
}
private:
owning_intrusive_list<solib>
solibs_from_rocm_sos (const std::vector<rocm_so> &sos) const;

View File

@@ -49,10 +49,6 @@
static void svr4_relocate_main_executable (void);
static void probes_table_remove_objfile_probes (struct objfile *objfile);
static void svr4_iterate_over_objfiles_in_search_order
(gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile);
/* On SVR4 systems, a list of symbols in the dynamic linker where
GDB can try to place a breakpoint to monitor shared library
@@ -3444,8 +3440,6 @@ void
set_solib_svr4_ops (gdbarch *gdbarch, gdbarch_make_solib_ops_ftype make_solib_ops)
{
set_gdbarch_make_solib_ops (gdbarch, make_solib_ops);
set_gdbarch_iterate_over_objfiles_in_search_order
(gdbarch, svr4_iterate_over_objfiles_in_search_order);
}
/* See solib-svr4.h. */
@@ -3598,10 +3592,10 @@ find_debug_base_for_solib (const solib *solib)
stay in the same namespace as that file. Otherwise, we only consider
the initial namespace. */
static void
svr4_iterate_over_objfiles_in_search_order
(gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile)
void
svr4_solib_ops::iterate_over_objfiles_in_search_order
(iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile) const
{
bool checked_current_objfile = false;
if (current_objfile != nullptr)
@@ -3611,11 +3605,14 @@ svr4_iterate_over_objfiles_in_search_order
if (current_objfile->separate_debug_objfile_backlink != nullptr)
current_objfile = current_objfile->separate_debug_objfile_backlink;
if (current_objfile == current_program_space->symfile_object_file)
abfd = current_program_space->exec_bfd ();
if (current_objfile == m_pspace->symfile_object_file)
abfd = m_pspace->exec_bfd ();
else
abfd = current_objfile->obfd.get ();
/* gdb_bfd_scan_elf_dyntag relies on the current program space. */
gdb_assert (m_pspace == current_program_space);
if (abfd != nullptr
&& gdb_bfd_scan_elf_dyntag (DT_SYMBOLIC, abfd, nullptr, nullptr) == 1)
{
@@ -3625,6 +3622,9 @@ svr4_iterate_over_objfiles_in_search_order
}
}
/* elf_locate_base relies on the current program space. */
gdb_assert (m_pspace == current_program_space);
/* The linker namespace to iterate identified by the address of its
r_debug object, defaulting to the initial namespace. */
CORE_ADDR initial = elf_locate_base ();
@@ -3633,7 +3633,7 @@ svr4_iterate_over_objfiles_in_search_order
if (debug_base == 0)
debug_base = initial;
for (objfile *objfile : current_program_space->objfiles ())
for (objfile *objfile : m_pspace->objfiles ())
{
if (checked_current_objfile && objfile == current_objfile)
continue;

View File

@@ -96,6 +96,9 @@ struct svr4_solib_ops : public solib_ops
int find_solib_ns (const solib &so) const override;
int num_active_namespaces () const override;
std::vector<const solib *> get_solibs_in_ns (int nsid) const override;
void iterate_over_objfiles_in_search_order
(iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile) const override;
/* Return the appropriate link map offsets table for the architecture. */
virtual link_map_offsets *fetch_link_map_offsets () const = 0;

View File

@@ -473,6 +473,18 @@ solib_ops::bfd_open (const char *pathname) const
return solib_bfd_open (pathname);
}
/* See solib.h. */
void
solib_ops::iterate_over_objfiles_in_search_order
(iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile) const
{
for (objfile *objfile : m_pspace->objfiles ())
if (cb (objfile))
return;
}
/* Given a pointer to one of the shared objects in our list of mapped
objects, use the recorded name to open a bfd descriptor for the
object, build a section table, relocate all the section addresses

View File

@@ -131,6 +131,12 @@ private:
/* A unique pointer to an solib. */
using solib_up = std::unique_ptr<solib>;
/* Callback type for the 'iterate_over_objfiles_in_search_order'
methods. */
using iterate_over_objfiles_in_search_order_cb_ftype
= gdb::function_view<bool (objfile *)>;
struct solib_ops
{
explicit solib_ops (program_space *pspace)
@@ -264,6 +270,18 @@ struct solib_ops
virtual std::vector<const solib *> get_solibs_in_ns (int ns) const
{ gdb_assert_not_reached ("namespaces not supported"); }
/* Iterate over all objfiles of the program space in the order that makes the
most sense for the architecture to make global symbol searches.
CB is a callback function passed an objfile to be searched. The iteration
stops if this function returns true.
If not nullptr, CURRENT_OBJFILE corresponds to the objfile being inspected
when the symbol search was requested. */
virtual void iterate_over_objfiles_in_search_order
(iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile) const;
protected:
/* The program space for which this solib_ops was created. */
program_space *m_pspace;

View File

@@ -2654,9 +2654,8 @@ lookup_global_or_static_symbol (const char *name,
/* Do a global search (of global blocks, heh). */
if (result.symbol == NULL)
gdbarch_iterate_over_objfiles_in_search_order
(objfile != NULL ? objfile->arch () : current_inferior ()->arch (),
[&result, block_index, name, domain] (struct objfile *objfile_iter)
current_program_space->iterate_over_objfiles_in_search_order
([&result, block_index, name, domain] (struct objfile *objfile_iter)
{
result = lookup_symbol_in_objfile (objfile_iter, block_index,
name, domain);
@@ -6575,9 +6574,8 @@ find_main_name (void)
/* Try to find language for main in psymtabs. */
bool symbol_found_p = false;
gdbarch_iterate_over_objfiles_in_search_order
(current_inferior ()->arch (),
[&symbol_found_p, pspace] (objfile *obj)
current_program_space->iterate_over_objfiles_in_search_order
([&symbol_found_p, pspace] (objfile *obj)
{
language lang
= obj->lookup_global_symbol_language ("main",

View File

@@ -550,43 +550,6 @@ windows_xfer_shared_library (const char* so_name, CORE_ADDR load_addr,
xml += "\"/></library>";
}
/* Implement the "iterate_over_objfiles_in_search_order" gdbarch
method. It searches all objfiles, starting with CURRENT_OBJFILE
first (if not NULL).
On Windows, the system behaves a little differently when two
objfiles each define a global symbol using the same name, compared
to other platforms such as GNU/Linux for instance. On GNU/Linux,
all instances of the symbol effectively get merged into a single
one, but on Windows, they remain distinct.
As a result, it usually makes sense to start global symbol searches
with the current objfile before expanding it to all other objfiles.
This helps for instance when a user debugs some code in a DLL that
refers to a global variable defined inside that DLL. When trying
to print the value of that global variable, it would be unhelpful
to print the value of another global variable defined with the same
name, but in a different DLL. */
static void
windows_iterate_over_objfiles_in_search_order
(gdbarch *gdbarch, iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile)
{
if (current_objfile)
{
if (cb (current_objfile))
return;
}
for (objfile *objfile : current_program_space->objfiles ())
if (objfile != current_objfile)
{
if (cb (objfile))
return;
}
}
static void
show_maint_show_all_tib (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
@@ -869,6 +832,9 @@ struct windows_solib_ops : target_solib_ops
using target_solib_ops::target_solib_ops;
void create_inferior_hook (int from_tty) const override;
void iterate_over_objfiles_in_search_order
(iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile) const override;
};
/* Return a new solib_ops for Windows systems. */
@@ -927,6 +893,43 @@ windows_solib_ops::create_inferior_hook (int from_tty) const
}
}
/* Implement the "iterate_over_objfiles_in_search_order" gdbarch
method. It searches all objfiles, starting with CURRENT_OBJFILE
first (if not NULL).
On Windows, the system behaves a little differently when two
objfiles each define a global symbol using the same name, compared
to other platforms such as GNU/Linux for instance. On GNU/Linux,
all instances of the symbol effectively get merged into a single
one, but on Windows, they remain distinct.
As a result, it usually makes sense to start global symbol searches
with the current objfile before expanding it to all other objfiles.
This helps for instance when a user debugs some code in a DLL that
refers to a global variable defined inside that DLL. When trying
to print the value of that global variable, it would be unhelpful
to print the value of another global variable defined with the same
name, but in a different DLL. */
void
windows_solib_ops::iterate_over_objfiles_in_search_order
(iterate_over_objfiles_in_search_order_cb_ftype cb,
objfile *current_objfile) const
{
if (current_objfile)
{
if (cb (current_objfile))
return;
}
for (objfile *objfile : m_pspace->objfiles ())
if (objfile != current_objfile)
{
if (cb (objfile))
return;
}
}
/* Common parts for gdbarch initialization for the Windows and Cygwin OS
ABIs. */
@@ -940,9 +943,6 @@ windows_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch)
`c:\Program Files\Foo App\mydll.dll', for example. */
set_gdbarch_has_dos_based_file_system (gdbarch, 1);
set_gdbarch_iterate_over_objfiles_in_search_order
(gdbarch, windows_iterate_over_objfiles_in_search_order);
set_gdbarch_make_solib_ops (gdbarch, make_windows_solib_ops);
set_gdbarch_get_siginfo_type (gdbarch, windows_get_siginfo_type);