From: Guinevere Larsen <guinevere@redhat.com>
To: Simon Marchi <simon.marchi@efficios.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH v2 4/4] gdb/solib: C++ify solib_ops
Date: Thu, 12 Jun 2025 09:56:06 -0300 [thread overview]
Message-ID: <fa840ac6-b0c1-41f4-ba87-9d0b5b326aac@redhat.com> (raw)
In-Reply-To: <20250609194146.137730-4-simon.marchi@efficios.com>
On 6/9/25 4:40 PM, Simon Marchi wrote:
> New in v2: added a precision in the commit message about some change in
> solib-rocm.c, about when / how rocm_solib_ops is set.
>
> Convert solib_ops into an abstract base class (with abstract methods,
> some of them with default implementations) and convert all the existing
> solib_ops instances to solib_ops derived classes / implementations.
>
> Prior to this patch, solib_ops is a structure holding function pointers,
> of which there are only a handful of global instances (in the
> `solib-*.c` files). When passing an `solib_ops *` around, it's a
> pointer to one of these instances. After this patch, there are no more
> global solib_ops instances. Instances are created as needed and stored
> in struct program_space. These instances could eventually be made to
> contain the program space-specific data, which is currently kept in
> per-program space registries (I have some pending patches for that).
>
> Prior to this patch, `gdbarch_so_ops` is a gdbarch method that returns a
> pointer to the appropriate solib_ops implementation for the gdbarch.
> This is replaced with the `gdbarch_new_solib_ops` method, which returns
> a new instance of the appropriate solib_ops implementation for this
> gdbarch. This requires introducing some factory functions for the
> various solib_ops implementation, to be used as `gdbarch_new_solib_ops`
> callbacks. For instance:
>
> solib_ops_up
> new_linux_ilp32_svr4_solib_ops ()
> {
> return std::make_unique<linux_ilp32_svr4_solib_ops> ();
> }
>
> The previous code is full of cases of tdep files copying some base
> solib_ops implementation, and overriding one or more function pointer
> (see ppc_linux_init_abi, for instance). I tried to convert all of this
> is a class hierarchy. I like that it's now possible to get a good
> static view of all the existing solib_ops variants. The hierarchy looks
> like this:
>
> solib_ops
> ├── aix_solib_ops
> ├── darwin_solib_ops
> ├── dsbt_solib_ops
> ├── frv_solib_ops
> ├── rocm_solib_ops
> ├── svr4_solib_ops
> │ ├── ilp32_svr4_solib_ops
> │ ├── lp64_svr4_solib_ops
> │ ├── linux_ilp32_svr4_solib_ops
> │ │ ├── mips_linux_ilp32_svr4_solib_ops
> │ │ └── ppc_linux_ilp32_svr4_solib_ops
> │ ├── linux_lp64_svr4_solib_ops
> │ │ └── mips_linux_lp64_svr4_solib_ops
> │ ├── mips_nbsd_ilp32_svr4_solib_ops
> │ ├── mips_nbsd_lp64_svr4_solib_ops
> │ ├── mips_fbsd_ilp32_svr4_solib_ops
> │ └── mips_fbsd_lp64_svr4_solib_ops
> └── target_solib_ops
> └── windows_solib_ops
>
> The solib-svr4 code has per-arch specialization to provide a
> link_map_offsets, containing the offsets of the interesting fields in
> `struct link_map` on that particular architecture. Prior to this patch,
> arches would set a callback returning the appropriate link_map_offsets
> by calling `set_solib_svr4_fetch_link_map_offsets`, which also happened
> to set the gdbarch's so_ops to `&svr_so_ops`. I converted this to an
> abstract virtual method of `struct svr4_solib_ops`, meaning that all
> classes deriving from svr4_solib_ops must provide a method returning the
> appropriate link_map_offsets for the architecture. I renamed
> `set_solib_svr4_fetch_link_map_offsets` to `set_solib_svr4_ops`. This
> function is still necessary because it also calls
> set_gdbarch_iterate_over_objfiles_in_search_order, but if it was not for
> that, we could get rid of it.
>
> There is a little "base class template" hack in mips-linux-tdep.c,
> because both mips_linux_ilp32_svr4_solib_ops and
> mips_linux_lp64_svr4_solib_ops need to derive from different SVR4 base
> classes (linux_ilp32_svr4_solib_ops and linux_lp64_svr4_solib_ops), but
> they both want to override the in_dynsym_resolve_code method with the
> same implementation. Let me know if there's a more straightforward way
> to do this.
>
> The solib_ops::supports_namespaces method is new: the support for
> namespaces was previously predicated by the presence or absence of a
> find_solib_ns method. It now needs to be explicit.
>
> There is a new progspace::release_solib_ops method, which is only needed
> for rocm_solib_ops. For the moment, rocm_solib_ops replaces and wraps
> the existing svr4_solib_ops instance, in order to combine the results of
> the two. The plan is to have a subsequent patch to allow program spaces to have
> multiple solib_ops, removing the need that release_solib_ops.
>
> Speaking of rocm_solib_ops: it previously overrode only a few methods by
> copying svr4_solib_ops and overwriting some function pointers. Now, it
> needs to implement all the methods that svr4_solib_ops implements, in
> order to forward the call. Otherwise, the default solib_ops method woul
> be called, hiding the svr4_solib_ops implementation. Again, this can be
> removed once we have support for multiple solib_ops in a program_space.
>
> There is also a small change in how rocm_solib_ops is activated. Prior
> to this patch, it's done at the end of rocm_update_solib_list. Since it
> overrides the function pointer in the static svr4_solib_ops, and then
> overwrites the host gdbarch, so_ops field, it's something that happens
> only once. After the patch though, we need to set rocm_solib_ops in all
> the program spaces that appear. We do this in
> rocm_solib_target_inferior_created and in the new
> rocm_solib_target_inferior_execd. After this, I will explore doing a
> change where rocm_solib_ops is only set when we detect the ROCm runtime
> is loaded.
>
> Change-Id: I5896b5bcbf8bdb024d67980380feba1ffefaa4c9
> ---
Hi!
I took a look over the entire series and the code looks good, and many
of the changes are very good. I don't really feel like I can properly
review this patch though, but I did ran it through aarch64 and ppc64le,
and I see no issues, so
Tested-By: Guinevere Larsen <guinevere@redhat.com>
--
Cheers,
Guinevere Larsen
She/Her/Hers
> gdb/Makefile.in | 3 +
> gdb/aarch64-fbsd-tdep.c | 3 +-
> gdb/aarch64-linux-tdep.c | 5 +-
> gdb/alpha-linux-tdep.c | 5 +-
> gdb/alpha-netbsd-tdep.c | 3 +-
> gdb/alpha-obsd-tdep.c | 3 +-
> gdb/amd-dbgapi-target.c | 18 +-
> gdb/amd-dbgapi-target.h | 5 +
> gdb/amd64-darwin-tdep.c | 2 +-
> gdb/amd64-fbsd-tdep.c | 3 +-
> gdb/amd64-gnu-tdep.c | 3 +-
> gdb/amd64-linux-tdep.c | 7 +-
> gdb/amd64-netbsd-tdep.c | 3 +-
> gdb/amd64-obsd-tdep.c | 3 +-
> gdb/amd64-sol2-tdep.c | 3 +-
> gdb/arc-linux-tdep.c | 4 +-
> gdb/arm-fbsd-tdep.c | 3 +-
> gdb/arm-linux-tdep.c | 4 +-
> gdb/arm-netbsd-tdep.c | 3 +-
> gdb/arm-obsd-tdep.c | 3 +-
> gdb/configure.tgt | 62 ++++--
> gdb/cris-linux-tdep.c | 5 +-
> gdb/csky-linux-tdep.c | 4 +-
> gdb/dicos-tdep.c | 2 +-
> gdb/frv-tdep.c | 3 +-
> gdb/frv-tdep.h | 3 -
> gdb/gdbarch-gen.c | 24 +--
> gdb/gdbarch-gen.h | 7 +-
> gdb/gdbarch.h | 1 +
> gdb/gdbarch_components.py | 12 +-
> gdb/hppa-bsd-tdep.c | 3 +-
> gdb/hppa-linux-tdep.c | 4 +-
> gdb/i386-darwin-tdep.c | 2 +-
> gdb/i386-fbsd-tdep.c | 3 +-
> gdb/i386-gnu-tdep.c | 3 +-
> gdb/i386-linux-tdep.c | 4 +-
> gdb/i386-netbsd-tdep.c | 3 +-
> gdb/i386-obsd-tdep.c | 3 +-
> gdb/i386-sol2-tdep.c | 3 +-
> gdb/ia64-linux-tdep.c | 4 +-
> gdb/infcmd.c | 2 +-
> gdb/infrun.c | 2 +-
> gdb/linux-tdep.c | 61 ------
> gdb/linux-tdep.h | 6 +-
> gdb/loongarch-linux-tdep.c | 8 +-
> gdb/m32r-linux-tdep.c | 4 +-
> gdb/m68k-bsd-tdep.c | 3 +-
> gdb/m68k-linux-tdep.c | 4 +-
> gdb/microblaze-linux-tdep.c | 4 +-
> gdb/mips-fbsd-tdep.c | 57 ++++-
> gdb/mips-linux-tdep.c | 65 ++++--
> gdb/mips-netbsd-tdep.c | 54 ++++-
> gdb/mips64-obsd-tdep.c | 3 +-
> gdb/mn10300-linux-tdep.c | 4 +-
> gdb/or1k-linux-tdep.c | 4 +-
> gdb/ppc-fbsd-tdep.c | 6 +-
> gdb/ppc-linux-tdep.c | 46 ++--
> gdb/ppc-netbsd-tdep.c | 3 +-
> gdb/ppc-obsd-tdep.c | 3 +-
> gdb/progspace.h | 17 +-
> gdb/riscv-fbsd-tdep.c | 7 +-
> gdb/riscv-linux-tdep.c | 8 +-
> gdb/rs6000-aix-tdep.c | 2 +-
> gdb/s390-linux-tdep.c | 7 +-
> gdb/sh-linux-tdep.c | 4 +-
> gdb/sh-netbsd-tdep.c | 3 +-
> gdb/solib-aix.c | 67 +++---
> gdb/solib-aix.h | 7 +-
> gdb/solib-darwin.c | 65 +++---
> gdb/solib-darwin.h | 6 +-
> gdb/solib-dsbt.c | 59 ++---
> gdb/solib-dsbt.h | 6 +-
> gdb/solib-frv.c | 63 +++---
> gdb/solib-frv.h | 28 +++
> gdb/solib-rocm.c | 148 +++++++++----
> gdb/solib-svr4-linux.c | 98 +++++++++
> gdb/solib-svr4-linux.h | 47 ++++
> gdb/solib-svr4.c | 415 +++++++++++++++---------------------
> gdb/solib-svr4.h | 126 +++++++++--
> gdb/solib-target.c | 40 ++--
> gdb/solib-target.h | 16 +-
> gdb/solib.c | 90 ++++----
> gdb/solib.h | 137 +++++++-----
> gdb/sparc-linux-tdep.c | 4 +-
> gdb/sparc-netbsd-tdep.c | 3 +-
> gdb/sparc-sol2-tdep.c | 3 +-
> gdb/sparc64-fbsd-tdep.c | 3 +-
> gdb/sparc64-linux-tdep.c | 4 +-
> gdb/sparc64-netbsd-tdep.c | 3 +-
> gdb/sparc64-obsd-tdep.c | 3 +-
> gdb/sparc64-sol2-tdep.c | 3 +-
> gdb/tic6x-linux-tdep.c | 2 +-
> gdb/tilegx-linux-tdep.c | 7 +-
> gdb/vax-netbsd-tdep.c | 3 +-
> gdb/windows-tdep.c | 26 ++-
> gdb/xtensa-linux-tdep.c | 4 +-
> gdb/xtensa-tdep.c | 3 +-
> 97 files changed, 1225 insertions(+), 892 deletions(-)
> create mode 100644 gdb/solib-frv.h
> create mode 100644 gdb/solib-svr4-linux.c
> create mode 100644 gdb/solib-svr4-linux.h
>
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 998203ce1e20..fc0c56564c23 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -891,6 +891,7 @@ ALL_TARGET_OBS = \
> solib-dsbt.o \
> solib-frv.o \
> solib-svr4.o \
> + solib-svr4-linux.o \
> sparc-linux-tdep.o \
> sparc-netbsd-tdep.o \
> sparc-obsd-tdep.o \
> @@ -1478,7 +1479,9 @@ HFILES_NO_SRCDIR = \
> solib.h \
> solib-aix.h \
> solib-darwin.h \
> + solib-frv.h \
> solib-svr4.h \
> + solib-svr4-linux.h \
> solib-target.h \
> source.h \
> source-cache.h \
> diff --git a/gdb/aarch64-fbsd-tdep.c b/gdb/aarch64-fbsd-tdep.c
> index 07fa38a37285..7227456b7a6f 100644
> --- a/gdb/aarch64-fbsd-tdep.c
> +++ b/gdb/aarch64-fbsd-tdep.c
> @@ -239,8 +239,7 @@ aarch64_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> /* Generic FreeBSD support. */
> fbsd_init_abi (info, gdbarch);
>
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
>
> tramp_frame_prepend_unwinder (gdbarch, &aarch64_fbsd_sigframe);
>
> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index a194ac809c23..43b5e2a781f0 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -23,6 +23,7 @@
> #include "extract-store-integer.h"
> #include "gdbarch.h"
> #include "glibc-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "linux-tdep.h"
> #include "svr4-tls-tdep.h"
> #include "aarch64-tdep.h"
> @@ -2768,9 +2769,7 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> tdep->lowest_pc = 0x8000;
>
> linux_init_abi (info, gdbarch, 1);
> -
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_lp64_svr4_solib_ops);
>
> /* Enable TLS support. */
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> diff --git a/gdb/alpha-linux-tdep.c b/gdb/alpha-linux-tdep.c
> index 2f6affa6a6d5..0ad731e567ed 100644
> --- a/gdb/alpha-linux-tdep.c
> +++ b/gdb/alpha-linux-tdep.c
> @@ -17,6 +17,7 @@
> along with this program. If not, see <http://www.gnu.org/licenses/>. */
>
> #include "frame.h"
> +#include "solib-svr4-linux.h"
> #include "osabi.h"
> #include "solib-svr4.h"
> #include "symtab.h"
> @@ -369,9 +370,7 @@ alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> tdep->jb_elt_size = 8;
>
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> -
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_lp64_svr4_solib_ops);
>
> /* Enable TLS support. */
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> diff --git a/gdb/alpha-netbsd-tdep.c b/gdb/alpha-netbsd-tdep.c
> index a24003918bba..1c1dc66791e7 100644
> --- a/gdb/alpha-netbsd-tdep.c
> +++ b/gdb/alpha-netbsd-tdep.c
> @@ -264,8 +264,7 @@ alphanbsd_init_abi (struct gdbarch_info info,
> set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
>
> /* NetBSD/alpha has SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
>
> tdep->dynamic_sigtramp_offset = alphanbsd_sigtramp_offset;
> tdep->pc_in_sigtramp = alphanbsd_pc_in_sigtramp;
> diff --git a/gdb/alpha-obsd-tdep.c b/gdb/alpha-obsd-tdep.c
> index b5ddbbc61cf4..6d153bb1b413 100644
> --- a/gdb/alpha-obsd-tdep.c
> +++ b/gdb/alpha-obsd-tdep.c
> @@ -109,8 +109,7 @@ alphaobsd_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
> set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
>
> /* OpenBSD/alpha has SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
> set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
>
> tdep->dynamic_sigtramp_offset = alphaobsd_sigtramp_offset;
> diff --git a/gdb/amd-dbgapi-target.c b/gdb/amd-dbgapi-target.c
> index 819b373da321..d7e9d040a557 100644
> --- a/gdb/amd-dbgapi-target.c
> +++ b/gdb/amd-dbgapi-target.c
> @@ -104,12 +104,26 @@ amd_dbgapi_lib_debug_module ()
>
> static gdb::observers::token amd_dbgapi_target_inferior_created_observer_token;
>
> +/* See amd-dbgapi-target.h. */
> +
> const gdb::observers::token &
> get_amd_dbgapi_target_inferior_created_observer_token ()
> {
> return amd_dbgapi_target_inferior_created_observer_token;
> }
>
> +/* inferior_execd observer token. */
> +
> +static gdb::observers::token amd_dbgapi_target_inferior_execd_observer_token;
> +
> +/* See amd-dbgapi-target.h. */
> +
> +const gdb::observers::token &
> +get_amd_dbgapi_target_inferior_execd_observer_token ()
> +{
> + return amd_dbgapi_target_inferior_execd_observer_token;
> +}
> +
> /* A type holding coordinates, etc. info for a given wave. */
>
> struct wave_coordinates
> @@ -2511,7 +2525,9 @@ _initialize_amd_dbgapi_target ()
> gdb::observers::inferior_created.attach
> (amd_dbgapi_target_inferior_created,
> amd_dbgapi_target_inferior_created_observer_token, "amd-dbgapi");
> - gdb::observers::inferior_execd.attach (amd_dbgapi_inferior_execd, "amd-dbgapi");
> + gdb::observers::inferior_execd.attach
> + (amd_dbgapi_inferior_execd, amd_dbgapi_target_inferior_execd_observer_token,
> + "amd-dbgapi");
> gdb::observers::inferior_forked.attach (amd_dbgapi_inferior_forked, "amd-dbgapi");
> gdb::observers::inferior_exit.attach (amd_dbgapi_inferior_exited, "amd-dbgapi");
> gdb::observers::inferior_pre_detach.attach (amd_dbgapi_inferior_pre_detach, "amd-dbgapi");
> diff --git a/gdb/amd-dbgapi-target.h b/gdb/amd-dbgapi-target.h
> index dd37ba3b82d2..fe3a50ba33b0 100644
> --- a/gdb/amd-dbgapi-target.h
> +++ b/gdb/amd-dbgapi-target.h
> @@ -54,6 +54,11 @@ using is_amd_dbgapi_handle
> const gdb::observers::token &
> get_amd_dbgapi_target_inferior_created_observer_token ();
>
> +/* Get the token of amd-dbgapi's inferior_execd observer. */
> +
> +const gdb::observers::token &
> + get_amd_dbgapi_target_inferior_execd_observer_token ();
> +
> /* Comparison operators for amd-dbgapi handle types. */
>
> template <typename T,
> diff --git a/gdb/amd64-darwin-tdep.c b/gdb/amd64-darwin-tdep.c
> index dde023e0fb08..f26ccc49f2c0 100644
> --- a/gdb/amd64-darwin-tdep.c
> +++ b/gdb/amd64-darwin-tdep.c
> @@ -113,7 +113,7 @@ x86_darwin_init_abi_64 (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> tdep->jb_pc_offset = 56;
>
> - set_gdbarch_so_ops (gdbarch, &darwin_so_ops);
> + set_gdbarch_new_solib_ops (gdbarch, new_darwin_solib_ops);
> }
>
> void _initialize_amd64_darwin_tdep ();
> diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c
> index eea01054aca0..b936a70bb54f 100644
> --- a/gdb/amd64-fbsd-tdep.c
> +++ b/gdb/amd64-fbsd-tdep.c
> @@ -328,8 +328,7 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> amd64fbsd_core_read_description);
>
> /* FreeBSD uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
>
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> svr4_fetch_objfile_link_map);
> diff --git a/gdb/amd64-gnu-tdep.c b/gdb/amd64-gnu-tdep.c
> index 602fa8e61160..3dfdf81adf8b 100644
> --- a/gdb/amd64-gnu-tdep.c
> +++ b/gdb/amd64-gnu-tdep.c
> @@ -218,8 +218,7 @@ amd64_gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> tdep->sc_num_regs = ARRAY_SIZE (amd64_gnu_sc_reg_offset);
>
> /* Hurd uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
> }
>
> void _initialize_amd64_gnu_tdep ();
> diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
> index e5a2ab9dd526..8a44d233caa3 100644
> --- a/gdb/amd64-linux-tdep.c
> +++ b/gdb/amd64-linux-tdep.c
> @@ -33,6 +33,7 @@
> #include "amd64-linux-tdep.h"
> #include "i386-linux-tdep.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "svr4-tls-tdep.h"
> #include "gdbsupport/x86-xstate.h"
> #include "inferior.h"
> @@ -2130,8 +2131,7 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> tdep->i386_syscall_record = amd64_linux_syscall_record;
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_lp64_svr4_solib_ops);
>
> /* Register DTrace handlers. */
> set_gdbarch_dtrace_parse_probe_argument (gdbarch, amd64_dtrace_parse_probe_argument);
> @@ -2344,8 +2344,7 @@ amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> tdep->i386_syscall_record = amd64_x32_linux_syscall_record;
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
> }
>
> void _initialize_amd64_linux_tdep ();
> diff --git a/gdb/amd64-netbsd-tdep.c b/gdb/amd64-netbsd-tdep.c
> index f4464b796118..d1e088003dba 100644
> --- a/gdb/amd64-netbsd-tdep.c
> +++ b/gdb/amd64-netbsd-tdep.c
> @@ -116,8 +116,7 @@ amd64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> tdep->sc_num_regs = ARRAY_SIZE (amd64nbsd_r_reg_offset);
>
> /* NetBSD uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
> }
>
> void _initialize_amd64nbsd_tdep ();
> diff --git a/gdb/amd64-obsd-tdep.c b/gdb/amd64-obsd-tdep.c
> index 5acc380e7995..bd3d655a5e08 100644
> --- a/gdb/amd64-obsd-tdep.c
> +++ b/gdb/amd64-obsd-tdep.c
> @@ -443,8 +443,7 @@ amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> bsd_uthread_set_collect_uthread (gdbarch, amd64obsd_collect_uthread);
>
> /* OpenBSD uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
>
> /* Unwind kernel trap frames correctly. */
> frame_unwind_prepend_unwinder (gdbarch, &amd64obsd_trapframe_unwind);
> diff --git a/gdb/amd64-sol2-tdep.c b/gdb/amd64-sol2-tdep.c
> index 84d5f87b814a..7c9fa1965aeb 100644
> --- a/gdb/amd64-sol2-tdep.c
> +++ b/gdb/amd64-sol2-tdep.c
> @@ -96,8 +96,7 @@ amd64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> tdep->sc_num_regs = tdep->gregset_num_regs;
>
> /* Solaris uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
> }
>
> void _initialize_amd64_sol2_tdep ();
> diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
> index adf669151d1e..dfa5fc225b07 100644
> --- a/gdb/arc-linux-tdep.c
> +++ b/gdb/arc-linux-tdep.c
> @@ -19,6 +19,7 @@
>
> /* GDB header files. */
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "objfiles.h"
> #include "opcode/arc.h"
> #include "osabi.h"
> @@ -736,8 +737,7 @@ arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
> and pointers (ILP32). */
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
> }
>
> /* Suppress warning from -Wmissing-prototypes. */
> diff --git a/gdb/arm-fbsd-tdep.c b/gdb/arm-fbsd-tdep.c
> index c9a466f91cd4..2e9024136f93 100644
> --- a/gdb/arm-fbsd-tdep.c
> +++ b/gdb/arm-fbsd-tdep.c
> @@ -300,8 +300,7 @@ arm_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> tramp_frame_prepend_unwinder (gdbarch, &arm_fbsd_sigframe);
>
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
>
> tdep->jb_pc = 24;
> tdep->jb_elt_size = 4;
> diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
> index 485a5d9cee36..316b3e733cef 100644
> --- a/gdb/arm-linux-tdep.c
> +++ b/gdb/arm-linux-tdep.c
> @@ -41,6 +41,7 @@
> #include "arm-tdep.h"
> #include "arm-linux-tdep.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "glibc-tdep.h"
> #include "arch-utils.h"
> #include "inferior.h"
> @@ -1801,8 +1802,7 @@ arm_linux_init_abi (struct gdbarch_info info,
> }
> tdep->jb_elt_size = ARM_LINUX_JB_ELEMENT_SIZE;
>
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> /* Single stepping. */
> set_gdbarch_software_single_step (gdbarch, arm_linux_software_single_step);
> diff --git a/gdb/arm-netbsd-tdep.c b/gdb/arm-netbsd-tdep.c
> index a16205436a9a..89fcbde10283 100644
> --- a/gdb/arm-netbsd-tdep.c
> +++ b/gdb/arm-netbsd-tdep.c
> @@ -156,8 +156,7 @@ arm_netbsd_elf_init_abi (struct gdbarch_info info,
> tdep->fp_model = ARM_FLOAT_SOFT_VFP;
>
> /* NetBSD ELF uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
> }
>
> void _initialize_arm_netbsd_tdep ();
> diff --git a/gdb/arm-obsd-tdep.c b/gdb/arm-obsd-tdep.c
> index 6fd4c8544719..a2ec923854ca 100644
> --- a/gdb/arm-obsd-tdep.c
> +++ b/gdb/arm-obsd-tdep.c
> @@ -83,8 +83,7 @@ armobsd_init_abi (struct gdbarch_info info,
> tramp_frame_prepend_unwinder (gdbarch, &armobsd_sigframe);
>
> /* OpenBSD/arm uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
> set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
>
> tdep->jb_pc = 24;
> diff --git a/gdb/configure.tgt b/gdb/configure.tgt
> index e9b306809dc1..255c77e9f8c0 100644
> --- a/gdb/configure.tgt
> +++ b/gdb/configure.tgt
> @@ -150,14 +150,15 @@ aarch64*-*-linux*)
> arch/aarch64-scalable-linux.o \
> arch/arm.o arch/arm-linux.o arch/arm-get-next-pcs.o \
> arm-tdep.o arm-linux-tdep.o \
> - glibc-tdep.o linux-tdep.o solib-svr4.o svr4-tls-tdep.o \
> + glibc-tdep.o linux-tdep.o solib-svr4.o \
> + solib-svr4-linux.o svr4-tls-tdep.o \
> symfile-mem.o linux-record.o"
> ;;
>
> alpha*-*-linux*)
> # Target: Little-endian Alpha running Linux
> gdb_target_obs="alpha-mdebug-tdep.o alpha-linux-tdep.o \
> - linux-tdep.o solib-svr4.o"
> + linux-tdep.o solib-svr4.o solib-svr4-linux.o"
> ;;
> alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu)
> # Target: NetBSD/alpha
> @@ -179,7 +180,7 @@ amdgcn*-*-*)
> am33_2.0*-*-linux*)
> # Target: Matsushita mn10300 (AM33) running Linux
> gdb_target_obs="mn10300-tdep.o mn10300-linux-tdep.o linux-tdep.o \
> - solib-svr4.o"
> + solib-svr4.o solib-svr4-linux.o"
> ;;
>
> arc*-*-elf32)
> @@ -189,7 +190,8 @@ arc*-*-elf32)
>
> arc*-*-linux*)
> # Target: ARC machine running Linux
> - gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o"
> + gdb_target_obs="arc-linux-tdep.o linux-tdep.o solib-svr4.o \
> + solib-svr4-linux.o"
> ;;
>
> arm*-wince-pe | arm*-*-mingw32ce*)
> @@ -199,7 +201,8 @@ arm*-wince-pe | arm*-*-mingw32ce*)
> arm*-*-linux*)
> # Target: ARM based machine running GNU/Linux
> gdb_target_obs="arch/arm-linux.o arm-linux-tdep.o glibc-tdep.o \
> - solib-svr4.o symfile-mem.o linux-tdep.o linux-record.o"
> + solib-svr4.o solib-svr4-linux.o symfile-mem.o \
> + linux-tdep.o linux-record.o"
> ;;
> arm*-*-freebsd*)
> # Target: FreeBSD/arm
> @@ -239,13 +242,14 @@ bpf-*-*)
>
> cris*)
> # Target: CRIS
> - gdb_target_obs="cris-tdep.o cris-linux-tdep.o linux-tdep.o solib-svr4.o"
> + gdb_target_obs="cris-tdep.o cris-linux-tdep.o linux-tdep.o \
> + solib-svr4.o solib-svr4-linux.o"
> ;;
>
> csky*-*-linux*)
> # Target: CSKY running GNU/Linux
> gdb_target_obs="csky-tdep.o csky-linux-tdep.o glibc-tdep.o \
> - linux-tdep.o solib-svr4.o"
> + linux-tdep.o solib-svr4.o solib-svr4-linux.o"
> ;;
>
> csky*-*-*)
> @@ -270,7 +274,8 @@ h8300-*-*)
> hppa*-*-linux*)
> # Target: HP PA-RISC running Linux
> gdb_target_obs="hppa-linux-tdep.o glibc-tdep.o \
> - linux-tdep.o solib-svr4.o symfile-mem.o"
> + linux-tdep.o solib-svr4.o solib-svr4-linux.o \
> + symfile-mem.o"
> ;;
> hppa*-*-netbsd*)
> # Target: NetBSD/hppa
> @@ -315,7 +320,7 @@ i[34567]86-*-linux*)
> # Target: Intel 386 running GNU/Linux
> gdb_target_obs="i386-linux-tdep.o \
> glibc-tdep.o \
> - solib-svr4.o symfile-mem.o \
> + solib-svr4.o solib-svr4-linux.o symfile-mem.o \
> linux-tdep.o linux-record.o \
> arch/i386-linux-tdesc.o \
> arch/x86-linux-tdesc-features.o"
> @@ -345,7 +350,7 @@ i[34567]86-*-go32* | i[34567]86-*-msdosdjgpp*)
> ia64-*-linux*)
> # Target: Intel IA-64 running GNU/Linux
> gdb_target_obs="ia64-linux-tdep.o linux-tdep.o \
> - solib-svr4.o symfile-mem.o"
> + solib-svr4.o solib-svr4-linux.o symfile-mem.o"
> ;;
> ia64-*-*vms*)
> # Target: Intel IA-64 running OpenVMS
> @@ -363,7 +368,8 @@ lm32-*-*)
> loongarch*-*-linux*)
> # Target: LoongArch running Linux
> gdb_target_obs="loongarch-linux-tdep.o glibc-tdep.o \
> - linux-tdep.o solib-svr4.o linux-record.o"
> + linux-tdep.o solib-svr4.o solib-svr4-linux.o \
> + linux-record.o"
> ;;
>
> m32c-*-*)
> @@ -374,8 +380,8 @@ m32c-*-*)
> m32r*-*-linux*)
> # Target: Renesas M32R running GNU/Linux
> gdb_target_obs="m32r-tdep.o m32r-linux-tdep.o \
> - glibc-tdep.o solib-svr4.o symfile-mem.o \
> - linux-tdep.o"
> + glibc-tdep.o solib-svr4.o solib-svr4-linux.o \
> + symfile-mem.o linux-tdep.o"
> ;;
> m32r*-*-*)
> # Target: Renesas m32r processor
> @@ -395,7 +401,8 @@ fido-*-elf*)
> m68*-*-linux*)
> # Target: Motorola m68k with a.out and ELF
> gdb_target_obs="m68k-tdep.o m68k-linux-tdep.o solib-svr4.o \
> - linux-tdep.o glibc-tdep.o symfile-mem.o"
> + solib-svr4-linux.o linux-tdep.o glibc-tdep.o \
> + symfile-mem.o"
> ;;
> m68*-*-netbsd* | m68*-*-knetbsd*-gnu)
> # Target: NetBSD/m68k
> @@ -415,7 +422,7 @@ mep-*-*)
> microblaze*-linux-*|microblaze*-*-linux*)
> # Target: Xilinx MicroBlaze running Linux
> gdb_target_obs="microblaze-tdep.o microblaze-linux-tdep.o solib-svr4.o \
> - symfile-mem.o linux-tdep.o"
> + solib-svr4-linux.o symfile-mem.o linux-tdep.o"
> ;;
> microblaze*-*-*)
> # Target: Xilinx MicroBlaze running standalone
> @@ -425,7 +432,8 @@ microblaze*-*-*)
> mips*-*-linux*)
> # Target: Linux/MIPS
> gdb_target_obs="mips-tdep.o mips-linux-tdep.o glibc-tdep.o \
> - solib-svr4.o symfile-mem.o linux-tdep.o"
> + solib-svr4.o solib-svr4-linux.o symfile-mem.o \
> + linux-tdep.o"
> ;;
> mips*-*-netbsd* | mips*-*-knetbsd*-gnu)
> # Target: MIPS running NetBSD
> @@ -469,7 +477,8 @@ nds32*-*-elf)
> or1k*-*-linux*)
> # Target: OpenCores OpenRISC 1000 32-bit running Linux
> gdb_target_obs="or1k-tdep.o or1k-linux-tdep.o solib-svr4.o \
> - symfile-mem.o glibc-tdep.o linux-tdep.o"
> + solib-svr4-linux.o symfile-mem.o glibc-tdep.o \
> + linux-tdep.o"
> ;;
>
> or1k-*-* | or1knd-*-*)
> @@ -503,7 +512,8 @@ powerpc-*-aix* | rs6000-*-* | powerpc64-*-aix*)
> powerpc*-*-linux*)
> # Target: PowerPC running Linux
> gdb_target_obs="rs6000-tdep.o ppc-linux-tdep.o ppc-sysv-tdep.o \
> - ppc64-tdep.o solib-svr4.o svr4-tls-tdep.o \
> + ppc64-tdep.o solib-svr4.o solib-svr4-linux.o \
> + svr4-tls-tdep.o \
> glibc-tdep.o symfile-mem.o linux-tdep.o \
> ravenscar-thread.o ppc-ravenscar-thread.o \
> linux-record.o \
> @@ -524,6 +534,7 @@ powerpc*-*-*)
> s390*-*-linux*)
> # Target: S390 running Linux
> gdb_target_obs="s390-linux-tdep.o s390-tdep.o solib-svr4.o \
> + solib-svr4-linux.o \
> linux-tdep.o linux-record.o symfile-mem.o \
> svr4-tls-tdep.o"
> ;;
> @@ -536,7 +547,8 @@ riscv*-*-freebsd*)
> riscv*-*-linux*)
> # Target: Linux/RISC-V
> gdb_target_obs="riscv-linux-tdep.o riscv-canonicalize-syscall-gen.o \
> - glibc-tdep.o linux-tdep.o solib-svr4.o symfile-mem.o \
> + glibc-tdep.o linux-tdep.o solib-svr4.o solib-svr4-linux.o \
> + symfile-mem.o \
> linux-record.o svr4-tls-tdep.o"
> ;;
>
> @@ -558,7 +570,7 @@ rx-*-*)
> sh*-*-linux*)
> # Target: GNU/Linux Super-H
> gdb_target_obs="sh-tdep.o sh-linux-tdep.o \
> - solib-svr4.o symfile-mem.o \
> + solib-svr4.o solib-svr4-linux.o symfile-mem.o \
> glibc-tdep.o linux-tdep.o"
> ;;
> sh*-*-netbsd* | sh*-*-knetbsd*-gnu)
> @@ -577,7 +589,8 @@ sh*)
> sparc-*-linux*)
> # Target: GNU/Linux SPARC
> gdb_target_obs="sparc-tdep.o \
> - sparc-linux-tdep.o solib-svr4.o symfile-mem.o \
> + sparc-linux-tdep.o solib-svr4.o solib-svr4-linux.o \
> + symfile-mem.o \
> linux-tdep.o \
> ravenscar-thread.o sparc-ravenscar-thread.o"
> if test "x$have_64_bit_bfd" = "xyes"; then
> @@ -590,7 +603,8 @@ sparc64-*-linux*)
> # Target: GNU/Linux UltraSPARC
> gdb_target_obs="sparc64-tdep.o \
> sparc64-linux-tdep.o sparc-tdep.o \
> - sparc-linux-tdep.o solib-svr4.o linux-tdep.o \
> + sparc-linux-tdep.o solib-svr4.o solib-svr4-linux.o \
> + linux-tdep.o \
> ravenscar-thread.o sparc-ravenscar-thread.o"
> ;;
> sparc*-*-freebsd* | sparc*-*-kfreebsd*-gnu)
> @@ -658,6 +672,7 @@ tic6x-*-*)
> tilegx-*-linux*)
> # Target: TILE-Gx
> gdb_target_obs="tilegx-tdep.o tilegx-linux-tdep.o solib-svr4.o \
> + solib-svr4-linux.o \
> symfile-mem.o glibc-tdep.o linux-tdep.o"
> ;;
>
> @@ -708,7 +723,8 @@ x86_64-*-linux*)
> # Target: GNU/Linux x86-64
> gdb_target_obs="amd64-linux-tdep.o ${i386_tobjs} \
> i386-linux-tdep.o glibc-tdep.o svr4-tls-tdep.o \
> - solib-svr4.o symfile-mem.o linux-tdep.o linux-record.o \
> + solib-svr4.o solib-svr4-linux.o symfile-mem.o \
> + linux-tdep.o linux-record.o \
> arch/i386-linux-tdesc.o arch/amd64-linux-tdesc.o \
> arch/x86-linux-tdesc-features.o"
> ;;
> diff --git a/gdb/cris-linux-tdep.c b/gdb/cris-linux-tdep.c
> index b2ac80d371c3..80e4c886fbfb 100644
> --- a/gdb/cris-linux-tdep.c
> +++ b/gdb/cris-linux-tdep.c
> @@ -23,6 +23,7 @@
>
> #include "osabi.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "solib-svr4.h"
> #include "symtab.h"
> #include "gdbarch.h"
> @@ -41,9 +42,7 @@ cris_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> svr4_fetch_objfile_link_map);
>
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_ilp32_fetch_link_map_offsets);
> -
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
> }
>
> void _initialize_cris_linux_tdep ();
> diff --git a/gdb/csky-linux-tdep.c b/gdb/csky-linux-tdep.c
> index 2afb35846bda..724542a10665 100644
> --- a/gdb/csky-linux-tdep.c
> +++ b/gdb/csky-linux-tdep.c
> @@ -22,6 +22,7 @@
> #include "osabi.h"
> #include "glibc-tdep.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "gdbarch.h"
> #include "solib-svr4.h"
> #include "regset.h"
> @@ -407,8 +408,7 @@ csky_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> /* Shared library handling. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> /* Enable TLS support. */
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> diff --git a/gdb/dicos-tdep.c b/gdb/dicos-tdep.c
> index 4dfac76654e8..fd43d9d859e6 100644
> --- a/gdb/dicos-tdep.c
> +++ b/gdb/dicos-tdep.c
> @@ -27,7 +27,7 @@
> void
> dicos_init_abi (struct gdbarch *gdbarch)
> {
> - set_gdbarch_so_ops (gdbarch, &solib_target_so_ops);
> + set_gdbarch_new_solib_ops (gdbarch, new_target_solib_ops);
>
> /* Every process, although has its own address space, sees the same
> list of shared libraries. There's no "main executable" in DICOS,
> diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c
> index 360887247ebc..9baa9cc24c21 100644
> --- a/gdb/frv-tdep.c
> +++ b/gdb/frv-tdep.c
> @@ -25,6 +25,7 @@
> #include "frame.h"
> #include "frame-unwind.h"
> #include "frame-base.h"
> +#include "solib-frv.h"
> #include "trad-frame.h"
> #include "dis-asm.h"
> #include "sim-regno.h"
> @@ -1554,7 +1555,7 @@ frv_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> set_gdbarch_convert_from_func_ptr_addr (gdbarch,
> frv_convert_from_func_ptr_addr);
>
> - set_gdbarch_so_ops (gdbarch, &frv_so_ops);
> + set_gdbarch_new_solib_ops (gdbarch, new_frv_solib_ops);
>
> /* Hook in ABI-specific overrides, if they have been registered. */
> gdbarch_init_osabi (info, gdbarch);
> diff --git a/gdb/frv-tdep.h b/gdb/frv-tdep.h
> index 07982b40db0f..7b51b428e9c4 100644
> --- a/gdb/frv-tdep.h
> +++ b/gdb/frv-tdep.h
> @@ -118,7 +118,4 @@ CORE_ADDR frv_fdpic_find_canonical_descriptor (CORE_ADDR entry_point);
> needed for TLS support. */
> CORE_ADDR frv_fetch_objfile_link_map (struct objfile *objfile);
>
> -struct solib_ops;
> -extern const solib_ops frv_so_ops;
> -
> #endif /* GDB_FRV_TDEP_H */
> diff --git a/gdb/gdbarch-gen.c b/gdb/gdbarch-gen.c
> index 32d16598940b..d191131d7b24 100644
> --- a/gdb/gdbarch-gen.c
> +++ b/gdb/gdbarch-gen.c
> @@ -157,7 +157,7 @@ struct gdbarch
> gdbarch_single_step_through_delay_ftype *single_step_through_delay = nullptr;
> gdbarch_print_insn_ftype *print_insn = default_print_insn;
> gdbarch_skip_trampoline_code_ftype *skip_trampoline_code = generic_skip_trampoline_code;
> - const solib_ops * so_ops = &solib_target_so_ops;
> + gdbarch_new_solib_ops_ftype *new_solib_ops = new_target_solib_ops;
> gdbarch_skip_solib_resolver_ftype *skip_solib_resolver = generic_skip_solib_resolver;
> gdbarch_in_solib_return_trampoline_ftype *in_solib_return_trampoline = generic_in_solib_return_trampoline;
> gdbarch_in_indirect_branch_thunk_ftype *in_indirect_branch_thunk = default_in_indirect_branch_thunk;
> @@ -425,7 +425,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
> /* Skip verify of single_step_through_delay, has predicate. */
> /* Skip verify of print_insn, invalid_p == 0. */
> /* Skip verify of skip_trampoline_code, invalid_p == 0. */
> - /* Skip verify of so_ops, invalid_p == 0. */
> + /* Skip verify of new_solib_ops, invalid_p == 0. */
> /* Skip verify of skip_solib_resolver, invalid_p == 0. */
> /* Skip verify of in_solib_return_trampoline, invalid_p == 0. */
> /* Skip verify of in_indirect_branch_thunk, invalid_p == 0. */
> @@ -966,8 +966,8 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
> "gdbarch_dump: skip_trampoline_code = <%s>\n",
> host_address_to_string (gdbarch->skip_trampoline_code));
> gdb_printf (file,
> - "gdbarch_dump: so_ops = %s\n",
> - host_address_to_string (gdbarch->so_ops));
> + "gdbarch_dump: new_solib_ops = <%s>\n",
> + host_address_to_string (gdbarch->new_solib_ops));
> gdb_printf (file,
> "gdbarch_dump: skip_solib_resolver = <%s>\n",
> host_address_to_string (gdbarch->skip_solib_resolver));
> @@ -3469,21 +3469,21 @@ set_gdbarch_skip_trampoline_code (struct gdbarch *gdbarch,
> gdbarch->skip_trampoline_code = skip_trampoline_code;
> }
>
> -const solib_ops *
> -gdbarch_so_ops (struct gdbarch *gdbarch)
> +solib_ops_up
> +gdbarch_new_solib_ops (struct gdbarch *gdbarch)
> {
> gdb_assert (gdbarch != NULL);
> - /* Skip verify of so_ops, invalid_p == 0. */
> + gdb_assert (gdbarch->new_solib_ops != NULL);
> if (gdbarch_debug >= 2)
> - gdb_printf (gdb_stdlog, "gdbarch_so_ops called\n");
> - return gdbarch->so_ops;
> + gdb_printf (gdb_stdlog, "gdbarch_new_solib_ops called\n");
> + return gdbarch->new_solib_ops ();
> }
>
> void
> -set_gdbarch_so_ops (struct gdbarch *gdbarch,
> - const solib_ops * so_ops)
> +set_gdbarch_new_solib_ops (struct gdbarch *gdbarch,
> + gdbarch_new_solib_ops_ftype new_solib_ops)
> {
> - gdbarch->so_ops = so_ops;
> + gdbarch->new_solib_ops = new_solib_ops;
> }
>
> CORE_ADDR
> diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h
> index 313a8f198fdb..b5a3762f438e 100644
> --- a/gdb/gdbarch-gen.h
> +++ b/gdb/gdbarch-gen.h
> @@ -818,10 +818,11 @@ typedef CORE_ADDR (gdbarch_skip_trampoline_code_ftype) (const frame_info_ptr &fr
> extern CORE_ADDR gdbarch_skip_trampoline_code (struct gdbarch *gdbarch, const frame_info_ptr &frame, CORE_ADDR pc);
> extern void set_gdbarch_skip_trampoline_code (struct gdbarch *gdbarch, gdbarch_skip_trampoline_code_ftype *skip_trampoline_code);
>
> -/* Vtable of solib operations functions. */
> +/* Return a newly-allocated solib_ops object capable of providing the solibs for this architecture. */
>
> -extern const solib_ops * gdbarch_so_ops (struct gdbarch *gdbarch);
> -extern void set_gdbarch_so_ops (struct gdbarch *gdbarch, const solib_ops * so_ops);
> +typedef solib_ops_up (gdbarch_new_solib_ops_ftype) ();
> +extern solib_ops_up gdbarch_new_solib_ops (struct gdbarch *gdbarch);
> +extern void set_gdbarch_new_solib_ops (struct gdbarch *gdbarch, gdbarch_new_solib_ops_ftype *new_solib_ops);
>
> /* If in_solib_dynsym_resolve_code() returns true, and SKIP_SOLIB_RESOLVER
> evaluates non-zero, this is the address where the debugger will place
> diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
> index 9feb2cc24e5b..6accbd2fd5ee 100644
> --- a/gdb/gdbarch.h
> +++ b/gdb/gdbarch.h
> @@ -30,6 +30,7 @@
> #include "displaced-stepping.h"
> #include "gdbsupport/gdb-checked-static-cast.h"
> #include "registry.h"
> +#include "solib.h"
>
> struct floatformat;
> struct ui_file;
> diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py
> index ec09d9550889..000729494611 100644
> --- a/gdb/gdbarch_components.py
> +++ b/gdb/gdbarch_components.py
> @@ -1431,12 +1431,12 @@ Function(
> invalid=False,
> )
>
> -Value(
> - comment="Vtable of solib operations functions.",
> - type="const solib_ops *",
> - name="so_ops",
> - predefault="&solib_target_so_ops",
> - printer="host_address_to_string (gdbarch->so_ops)",
> +Function(
> + comment="Return a newly-allocated solib_ops object capable of providing the solibs for this architecture.",
> + type="solib_ops_up",
> + name="new_solib_ops",
> + params=[],
> + predefault="new_target_solib_ops",
> invalid=False,
> )
>
> diff --git a/gdb/hppa-bsd-tdep.c b/gdb/hppa-bsd-tdep.c
> index db6c92f8aab5..f7269c921b55 100644
> --- a/gdb/hppa-bsd-tdep.c
> +++ b/gdb/hppa-bsd-tdep.c
> @@ -128,8 +128,7 @@ hppabsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code);
>
> /* OpenBSD and NetBSD use SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
>
> /* Hook in the DWARF CFI frame unwinder. */
> dwarf2_frame_set_init_reg (gdbarch, hppabsd_dwarf2_frame_init_reg);
> diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c
> index 16cdd4540165..b6a43ffa740c 100644
> --- a/gdb/hppa-linux-tdep.c
> +++ b/gdb/hppa-linux-tdep.c
> @@ -32,6 +32,7 @@
> #include "regcache.h"
> #include "hppa-tdep.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "elf/common.h"
>
> /* Map DWARF DBX register numbers to GDB register numbers. */
> @@ -499,8 +500,7 @@ hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> frame_unwind_append_unwinder (gdbarch, &hppa_linux_sigtramp_frame_unwind);
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> tdep->in_solib_call_trampoline = hppa_in_solib_call_trampoline;
> set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code);
> diff --git a/gdb/i386-darwin-tdep.c b/gdb/i386-darwin-tdep.c
> index 6180e0293a6e..9a1f39273942 100644
> --- a/gdb/i386-darwin-tdep.c
> +++ b/gdb/i386-darwin-tdep.c
> @@ -271,7 +271,7 @@ i386_darwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> alignment. */
> set_gdbarch_long_double_bit (gdbarch, 128);
>
> - set_gdbarch_so_ops (gdbarch, &darwin_so_ops);
> + set_gdbarch_new_solib_ops (gdbarch, new_darwin_solib_ops);
> }
>
> static enum gdb_osabi
> diff --git a/gdb/i386-fbsd-tdep.c b/gdb/i386-fbsd-tdep.c
> index 72237d89cfcc..5840b618e8fd 100644
> --- a/gdb/i386-fbsd-tdep.c
> +++ b/gdb/i386-fbsd-tdep.c
> @@ -402,8 +402,7 @@ i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> i386fbsd_core_read_description);
>
> /* FreeBSD uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
>
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> svr4_fetch_objfile_link_map);
> diff --git a/gdb/i386-gnu-tdep.c b/gdb/i386-gnu-tdep.c
> index 97fbc697b845..18fb2a6d2098 100644
> --- a/gdb/i386-gnu-tdep.c
> +++ b/gdb/i386-gnu-tdep.c
> @@ -180,8 +180,7 @@ i386gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* Hurd uses SVR4-style shared libraries. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
>
> /* Hurd uses the dynamic linker included in the GNU C Library. */
> set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
> diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
> index 4b05cc6870b5..93b518d93afc 100644
> --- a/gdb/i386-linux-tdep.c
> +++ b/gdb/i386-linux-tdep.c
> @@ -30,6 +30,7 @@
> #include "i386-tdep.h"
> #include "i386-linux-tdep.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "utils.h"
> #include "glibc-tdep.h"
> #include "solib-svr4.h"
> @@ -1461,8 +1462,7 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> /* GNU/Linux uses the dynamic linker included in the GNU C Library. */
> set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
> diff --git a/gdb/i386-netbsd-tdep.c b/gdb/i386-netbsd-tdep.c
> index 701ce048b5e8..d9a3e375d621 100644
> --- a/gdb/i386-netbsd-tdep.c
> +++ b/gdb/i386-netbsd-tdep.c
> @@ -415,8 +415,7 @@ i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> i386_elf_init_abi (info, gdbarch);
>
> /* NetBSD ELF uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
>
> /* NetBSD ELF uses -fpcc-struct-return by default. */
> tdep->struct_return = pcc_struct_return;
> diff --git a/gdb/i386-obsd-tdep.c b/gdb/i386-obsd-tdep.c
> index be656688b369..0ea12d82f1b0 100644
> --- a/gdb/i386-obsd-tdep.c
> +++ b/gdb/i386-obsd-tdep.c
> @@ -441,8 +441,7 @@ i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> frame_unwind_prepend_unwinder (gdbarch, &i386obsd_trapframe_unwind);
>
> /* OpenBSD ELF uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
> }
>
> void _initialize_i386obsd_tdep ();
> diff --git a/gdb/i386-sol2-tdep.c b/gdb/i386-sol2-tdep.c
> index e842236718d6..ffc95f41f0ca 100644
> --- a/gdb/i386-sol2-tdep.c
> +++ b/gdb/i386-sol2-tdep.c
> @@ -86,8 +86,7 @@ i386_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> tdep->sc_num_regs = tdep->gregset_num_regs;
>
> /* Solaris has SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
> }
> \f
>
> diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c
> index c45b2bb26e89..d84848f1c35a 100644
> --- a/gdb/ia64-linux-tdep.c
> +++ b/gdb/ia64-linux-tdep.c
> @@ -26,6 +26,7 @@
> #include "solib-svr4.h"
> #include "symtab.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "regset.h"
>
> #include <ctype.h>
> @@ -235,8 +236,7 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
>
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_lp64_svr4_solib_ops);
>
> /* Enable TLS support. */
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 1adad5c3eaa3..6c67a918f57a 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -260,7 +260,7 @@ post_create_inferior (int from_tty, bool set_pspace_solib_ops)
>
> if (set_pspace_solib_ops)
> current_program_space->set_solib_ops
> - (*gdbarch_so_ops (current_inferior ()->arch ()));
> + (gdbarch_new_solib_ops (current_inferior ()->arch ()));
>
> if (current_program_space->exec_bfd ())
> {
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 5cdf66d26dcb..5c652045e8ac 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -1383,7 +1383,7 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
> target_find_description ();
>
> current_program_space->set_solib_ops
> - (*gdbarch_so_ops (following_inferior->arch ()));
> + (gdbarch_new_solib_ops (following_inferior->arch ()));
> gdb::observers::inferior_execd.notify (execing_inferior, following_inferior);
>
> breakpoint_re_set ();
> diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
> index 1e339b59e2e8..12c05f31d53a 100644
> --- a/gdb/linux-tdep.c
> +++ b/gdb/linux-tdep.c
> @@ -3118,64 +3118,3 @@ more information about this file, refer to the manpage of proc(5) and core(5).")
> &setlist, &showlist);
>
> }
> -
> -/* Fetch (and possibly build) an appropriate `link_map_offsets' for
> - ILP32/LP64 Linux systems which don't have the r_ldsomap field. */
> -
> -link_map_offsets *
> -linux_ilp32_fetch_link_map_offsets ()
> -{
> - static link_map_offsets lmo;
> - static link_map_offsets *lmp = nullptr;
> -
> - if (lmp == nullptr)
> - {
> - lmp = &lmo;
> -
> - lmo.r_version_offset = 0;
> - lmo.r_version_size = 4;
> - lmo.r_map_offset = 4;
> - lmo.r_brk_offset = 8;
> - lmo.r_ldsomap_offset = -1;
> - lmo.r_next_offset = 20;
> -
> - /* Everything we need is in the first 20 bytes. */
> - lmo.link_map_size = 20;
> - lmo.l_addr_offset = 0;
> - lmo.l_name_offset = 4;
> - lmo.l_ld_offset = 8;
> - lmo.l_next_offset = 12;
> - lmo.l_prev_offset = 16;
> - }
> -
> - return lmp;
> -}
> -
> -link_map_offsets *
> -linux_lp64_fetch_link_map_offsets ()
> -{
> - static link_map_offsets lmo;
> - static link_map_offsets *lmp = nullptr;
> -
> - if (lmp == nullptr)
> - {
> - lmp = &lmo;
> -
> - lmo.r_version_offset = 0;
> - lmo.r_version_size = 4;
> - lmo.r_map_offset = 8;
> - lmo.r_brk_offset = 16;
> - lmo.r_ldsomap_offset = -1;
> - lmo.r_next_offset = 40;
> -
> - /* Everything we need is in the first 40 bytes. */
> - lmo.link_map_size = 40;
> - lmo.l_addr_offset = 0;
> - lmo.l_name_offset = 8;
> - lmo.l_ld_offset = 16;
> - lmo.l_next_offset = 24;
> - lmo.l_prev_offset = 32;
> - }
> -
> - return lmp;
> -}
> diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h
> index 7485fc132a63..3d82ea5bbdf3 100644
> --- a/gdb/linux-tdep.h
> +++ b/gdb/linux-tdep.h
> @@ -22,6 +22,7 @@
>
> #include "bfd.h"
> #include "displaced-stepping.h"
> +#include "solib.h"
>
> struct inferior;
> struct regcache;
> @@ -112,9 +113,4 @@ extern CORE_ADDR linux_get_hwcap2 (const std::optional<gdb::byte_vector> &auxv,
>
> extern CORE_ADDR linux_get_hwcap2 ();
>
> -/* Fetch (and possibly build) an appropriate `struct link_map_offsets'
> - for ILP32 and LP64 Linux systems. */
> -extern struct link_map_offsets *linux_ilp32_fetch_link_map_offsets ();
> -extern struct link_map_offsets *linux_lp64_fetch_link_map_offsets ();
> -
> #endif /* GDB_LINUX_TDEP_H */
> diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c
> index 38485e04b1ec..af6474e8390b 100644
> --- a/gdb/loongarch-linux-tdep.c
> +++ b/gdb/loongarch-linux-tdep.c
> @@ -25,6 +25,7 @@
> #include "inferior.h"
> #include "linux-record.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "loongarch-tdep.h"
> #include "record-full.h"
> #include "regset.h"
> @@ -1145,10 +1146,9 @@ loongarch_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> linux_init_abi (info, gdbarch, 0);
>
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - info.bfd_arch_info->bits_per_address == 32
> - ? linux_ilp32_fetch_link_map_offsets
> - : linux_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, (info.bfd_arch_info->bits_per_address == 32
> + ? new_linux_ilp32_svr4_solib_ops
> + : new_linux_lp64_svr4_solib_ops));
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> diff --git a/gdb/m32r-linux-tdep.c b/gdb/m32r-linux-tdep.c
> index 4fbe7d9927c0..52061923f8eb 100644
> --- a/gdb/m32r-linux-tdep.c
> +++ b/gdb/m32r-linux-tdep.c
> @@ -36,6 +36,7 @@
>
> #include "m32r-tdep.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "gdbarch.h"
>
> \f
> @@ -461,8 +462,7 @@ m32r_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> /* Core file support. */
> set_gdbarch_iterate_over_regset_sections
> diff --git a/gdb/m68k-bsd-tdep.c b/gdb/m68k-bsd-tdep.c
> index 09c57c6e61da..8155f7d2fe06 100644
> --- a/gdb/m68k-bsd-tdep.c
> +++ b/gdb/m68k-bsd-tdep.c
> @@ -147,8 +147,7 @@ m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> tdep->struct_return = pcc_struct_return;
>
> /* NetBSD ELF uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
> }
>
> void _initialize_m68kbsd_tdep ();
> diff --git a/gdb/m68k-linux-tdep.c b/gdb/m68k-linux-tdep.c
> index cfc37abc59c6..baaf0d4c9740 100644
> --- a/gdb/m68k-linux-tdep.c
> +++ b/gdb/m68k-linux-tdep.c
> @@ -35,6 +35,7 @@
> #include "observable.h"
> #include "elf/common.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "regset.h"
> \f
> /* Offsets (in target ints) into jmp_buf. */
> @@ -407,8 +408,7 @@ m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> /* Shared library handling. */
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> /* GNU/Linux uses the dynamic linker included in the GNU C Library. */
> set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
> diff --git a/gdb/microblaze-linux-tdep.c b/gdb/microblaze-linux-tdep.c
> index 8dcbeaafb834..9d18fbe7aa04 100644
> --- a/gdb/microblaze-linux-tdep.c
> +++ b/gdb/microblaze-linux-tdep.c
> @@ -35,6 +35,7 @@
> #include "frame-unwind.h"
> #include "tramp-frame.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
>
> static int
> microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch,
> @@ -125,8 +126,7 @@ microblaze_linux_init_abi (struct gdbarch_info info,
> microblaze_linux_memory_remove_breakpoint);
>
> /* Shared library handling. */
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> /* Trampolines. */
> tramp_frame_prepend_unwinder (gdbarch,
> diff --git a/gdb/mips-fbsd-tdep.c b/gdb/mips-fbsd-tdep.c
> index c280527b6abb..f00ab31db3c9 100644
> --- a/gdb/mips-fbsd-tdep.c
> +++ b/gdb/mips-fbsd-tdep.c
> @@ -476,12 +476,28 @@ mips_fbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
> return fbsd_skip_solib_resolver (gdbarch, pc);
> }
>
> -/* FreeBSD/mips uses a slightly different `struct link_map' than the
> - other FreeBSD platforms as it includes an additional `l_off'
> - member. */
> +/* solib_ops for ILP32 FreeBSD/MIPS systems. */
>
> -static struct link_map_offsets *
> -mips_fbsd_ilp32_fetch_link_map_offsets (void)
> +struct mips_fbsd_ilp32_solib_ops : public svr4_solib_ops
> +{
> + /* FreeBSD/MIPS uses a slightly different `struct link_map' than the
> + other FreeBSD platforms as it includes an additional `l_off' member. */
> +
> + link_map_offsets *fetch_link_map_offsets () const override;
> +};
> +
> +/* Return a new solib_ops for ILP32 FreeBSD/MIPS systems. */
> +
> +static solib_ops_up
> +new_mips_fbsd_ilp32_solib_ops ()
> +{
> + return std::make_unique<mips_fbsd_ilp32_solib_ops> ();
> +}
> +
> +/* See mips_fbsd_ilp32_solib_ops. */
> +
> +link_map_offsets *
> +mips_fbsd_ilp32_solib_ops::fetch_link_map_offsets () const
> {
> static struct link_map_offsets lmo;
> static struct link_map_offsets *lmp = NULL;
> @@ -508,8 +524,28 @@ mips_fbsd_ilp32_fetch_link_map_offsets (void)
> return lmp;
> }
>
> -static struct link_map_offsets *
> -mips_fbsd_lp64_fetch_link_map_offsets (void)
> +/* solib_ops for LP64 FreeBSD/MIPS systems. */
> +
> +struct mips_fbsd_lp64_solib_ops : public svr4_solib_ops
> +{
> + /* FreeBSD/MIPS uses a slightly different `struct link_map' than the
> + other FreeBSD platforms as it includes an additional `l_off' member. */
> +
> + link_map_offsets *fetch_link_map_offsets () const override;
> +};
> +
> +/* Return a new solib_ops for LP64 FreeBSD/MIPS systems. */
> +
> +static solib_ops_up
> +new_mips_fbsd_lp64_solib_ops ()
> +{
> + return std::make_unique<mips_fbsd_lp64_solib_ops> ();
> +}
> +
> +/* See mips_fbsd_lp64_solib_ops. */
> +
> +link_map_offsets *
> +mips_fbsd_lp64_solib_ops::fetch_link_map_offsets () const
> {
> static struct link_map_offsets lmo;
> static struct link_map_offsets *lmp = NULL;
> @@ -565,10 +601,9 @@ mips_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> set_gdbarch_skip_solib_resolver (gdbarch, mips_fbsd_skip_solib_resolver);
>
> /* FreeBSD/mips has SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
> - mips_fbsd_ilp32_fetch_link_map_offsets :
> - mips_fbsd_lp64_fetch_link_map_offsets));
> + set_solib_svr4_ops (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32
> + ? new_mips_fbsd_ilp32_solib_ops
> + : new_mips_fbsd_lp64_solib_ops));
> }
>
> void _initialize_mips_fbsd_tdep ();
> diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
> index bf3df3697e15..29633d8298df 100644
> --- a/gdb/mips-linux-tdep.c
> +++ b/gdb/mips-linux-tdep.c
> @@ -36,6 +36,7 @@
> #include "mips-linux-tdep.h"
> #include "glibc-tdep.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "xml-syscall.h"
> #include "gdbsupport/gdb_signals.h"
> #include "inferior.h"
> @@ -45,8 +46,6 @@
> #include "features/mips64-linux.c"
> #include "features/mips64-dsp-linux.c"
>
> -static solib_ops mips_svr4_so_ops;
> -
> /* This enum represents the signals' numbers on the MIPS
> architecture. It just contains the signal definitions which are
> different from the generic implementation.
> @@ -666,15 +665,22 @@ mips_linux_in_dynsym_stub (CORE_ADDR pc)
> return 1;
> }
>
> -/* Return true iff PC belongs to the dynamic linker resolution
> - code, a PLT entry, or a lazy binding stub. */
> +/* Mix-in class to add Linux/MIPS-specific methods to a base solib_ops
> + class. */
>
> -static bool
> -mips_linux_in_dynsym_resolve_code (CORE_ADDR pc)
> +template <typename Base>
> +struct mips_linux_svr4_solib_ops : public Base
> +{
> + bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
> +};
> +
> +template <typename Base>
> +bool
> +mips_linux_svr4_solib_ops<Base>::in_dynsym_resolve_code (CORE_ADDR pc) const
> {
> /* Check whether PC is in the dynamic linker. This also checks
> whether it is in the .plt section, used by non-PIC executables. */
> - if (svr4_in_dynsym_resolve_code (pc))
> + if (Base::in_dynsym_resolve_code (pc))
> return true;
>
> /* Likewise for the stubs. They live in the .MIPS.stubs section these
> @@ -686,6 +692,32 @@ mips_linux_in_dynsym_resolve_code (CORE_ADDR pc)
> return false;
> }
>
> +/* solib_ops for ILP32 Linux/MIPS systems. */
> +
> +using mips_linux_ilp32_svr4_solib_ops
> + = mips_linux_svr4_solib_ops<linux_ilp32_svr4_solib_ops>;
> +
> +/* Return a new solib_ops for ILP32 Linux/MIPS systems. */
> +
> +static solib_ops_up
> +new_mips_linux_ilp32_svr4_solib_ops ()
> +{
> + return std::make_unique<mips_linux_ilp32_svr4_solib_ops> ();
> +}
> +
> +/* solib_ops for LP64 Linux/MIPS systems. */
> +
> +using mips_linux_lp64_svr4_solib_ops
> + = mips_linux_svr4_solib_ops<linux_lp64_svr4_solib_ops>;
> +
> +/* Return a new solib_ops for LP64 Linux/MIPS systems. */
> +
> +static solib_ops_up
> +new_mips_linux_lp64_svr4_solib_ops ()
> +{
> + return std::make_unique<mips_linux_lp64_svr4_solib_ops> ();
> +}
> +
> /* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c,
> and glibc_skip_solib_resolver in glibc-tdep.c. The normal glibc
> implementation of this triggers at "fixup" from the same objfile as
> @@ -1537,8 +1569,7 @@ mips_linux_init_abi (struct gdbarch_info info,
> case MIPS_ABI_O32:
> set_gdbarch_get_longjmp_target (gdbarch,
> mips_linux_get_longjmp_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_mips_linux_ilp32_svr4_solib_ops);
> tramp_frame_prepend_unwinder (gdbarch, µmips_linux_o32_sigframe);
> tramp_frame_prepend_unwinder (gdbarch,
> µmips_linux_o32_rt_sigframe);
> @@ -1549,8 +1580,7 @@ mips_linux_init_abi (struct gdbarch_info info,
> case MIPS_ABI_N32:
> set_gdbarch_get_longjmp_target (gdbarch,
> mips_linux_get_longjmp_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_mips_linux_ilp32_svr4_solib_ops);
> set_gdbarch_long_double_bit (gdbarch, 128);
> set_gdbarch_long_double_format (gdbarch, floatformats_ieee_quad);
> tramp_frame_prepend_unwinder (gdbarch,
> @@ -1561,8 +1591,7 @@ mips_linux_init_abi (struct gdbarch_info info,
> case MIPS_ABI_N64:
> set_gdbarch_get_longjmp_target (gdbarch,
> mips64_linux_get_longjmp_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_mips_linux_lp64_svr4_solib_ops);
> set_gdbarch_long_double_bit (gdbarch, 128);
> set_gdbarch_long_double_format (gdbarch, floatformats_ieee_quad);
> tramp_frame_prepend_unwinder (gdbarch,
> @@ -1582,16 +1611,6 @@ mips_linux_init_abi (struct gdbarch_info info,
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> svr4_fetch_objfile_link_map);
>
> - /* Initialize this lazily, to avoid an initialization order
> - dependency on solib-svr4.c's _initialize routine. */
> - if (mips_svr4_so_ops.in_dynsym_resolve_code == NULL)
> - {
> - mips_svr4_so_ops = svr4_so_ops;
> - mips_svr4_so_ops.in_dynsym_resolve_code
> - = mips_linux_in_dynsym_resolve_code;
> - }
> - set_gdbarch_so_ops (gdbarch, &mips_svr4_so_ops);
> -
> set_gdbarch_write_pc (gdbarch, mips_linux_write_pc);
>
> set_gdbarch_core_read_description (gdbarch,
> diff --git a/gdb/mips-netbsd-tdep.c b/gdb/mips-netbsd-tdep.c
> index c9bdaa6800bb..165bf95c1881 100644
> --- a/gdb/mips-netbsd-tdep.c
> +++ b/gdb/mips-netbsd-tdep.c
> @@ -288,13 +288,27 @@ mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno)
> || regno == mips_regnum (gdbarch)->fp_implementation_revision);
> }
>
> -/* Shared library support. */
> +/* solib_ops for ILP32 NetBSD/MIPS systems. */
>
> -/* NetBSD/mips uses a slightly different `struct link_map' than the
> - other NetBSD platforms. */
> +struct mips_nbsd_ilp32_svr4_solib_ops : public svr4_solib_ops
> +{
> + /* NetBSD/MIPS uses a slightly different `struct link_map' than the
> + other NetBSD platforms. */
> + link_map_offsets *fetch_link_map_offsets () const override;
> +};
>
> -static struct link_map_offsets *
> -mipsnbsd_ilp32_fetch_link_map_offsets (void)
> +/* Return a new solib_ops for ILP32 NetBSD/MIPS systems. */
> +
> +static solib_ops_up
> +new_mips_nbsd_ilp32_svr4_solib_ops ()
> +{
> + return std::make_unique<mips_nbsd_ilp32_svr4_solib_ops> ();
> +}
> +
> +/* See mips_nbsd_ilp32_svr4_solib_ops. */
> +
> +link_map_offsets *
> +mips_nbsd_ilp32_svr4_solib_ops::fetch_link_map_offsets () const
> {
> static struct link_map_offsets lmo;
> static struct link_map_offsets *lmp = NULL;
> @@ -322,8 +336,27 @@ mipsnbsd_ilp32_fetch_link_map_offsets (void)
> return lmp;
> }
>
> -static struct link_map_offsets *
> -mipsnbsd_lp64_fetch_link_map_offsets (void)
> +/* solib_ops for LP64 NetBSD/MIPS systems. */
> +
> +struct mips_nbsd_lp64_svr4_solib_ops : public svr4_solib_ops
> +{
> + /* NetBSD/MIPS uses a slightly different `struct link_map' than the
> + other NetBSD platforms. */
> + link_map_offsets *fetch_link_map_offsets () const override;
> +};
> +
> +/* Return a new solib_ops for LP64 NetBSD/MIPS systems. */
> +
> +static solib_ops_up
> +new_mips_nbsd_lp64_svr4_solib_ops ()
> +{
> + return std::make_unique<mips_nbsd_lp64_svr4_solib_ops> ();
> +}
> +
> +/* See mips_nbsd_lp64_svr4_solib_ops. */
> +
> +link_map_offsets *
> +mips_nbsd_lp64_svr4_solib_ops::fetch_link_map_offsets () const
> {
> static struct link_map_offsets lmo;
> static struct link_map_offsets *lmp = NULL;
> @@ -369,10 +402,9 @@ mipsnbsd_init_abi (struct gdbarch_info info,
> set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
>
> /* NetBSD/mips has SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
> - mipsnbsd_ilp32_fetch_link_map_offsets :
> - mipsnbsd_lp64_fetch_link_map_offsets));
> + set_solib_svr4_ops (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32
> + ? new_mips_nbsd_ilp32_svr4_solib_ops
> + : new_mips_nbsd_lp64_svr4_solib_ops));
> }
>
> void _initialize_mipsnbsd_tdep ();
> diff --git a/gdb/mips64-obsd-tdep.c b/gdb/mips64-obsd-tdep.c
> index d0c9a1c86587..2d856c1442f2 100644
> --- a/gdb/mips64-obsd-tdep.c
> +++ b/gdb/mips64-obsd-tdep.c
> @@ -150,8 +150,7 @@ mips64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> obsd_init_abi(info, gdbarch);
>
> /* OpenBSD/mips64 has SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
> }
>
> void _initialize_mips64obsd_tdep ();
> diff --git a/gdb/mn10300-linux-tdep.c b/gdb/mn10300-linux-tdep.c
> index 3334ca0cc7d2..0fa5db972151 100644
> --- a/gdb/mn10300-linux-tdep.c
> +++ b/gdb/mn10300-linux-tdep.c
> @@ -29,6 +29,7 @@
> #include "trad-frame.h"
> #include "tramp-frame.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "gdbarch.h"
>
> /* Transliterated from <asm-mn10300/elf.h>... */
> @@ -707,8 +708,7 @@ am33_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> set_gdbarch_iterate_over_regset_sections
> (gdbarch, am33_iterate_over_regset_sections);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> tramp_frame_prepend_unwinder (gdbarch, &am33_linux_sigframe);
> tramp_frame_prepend_unwinder (gdbarch, &am33_linux_rt_sigframe);
> diff --git a/gdb/or1k-linux-tdep.c b/gdb/or1k-linux-tdep.c
> index 4784e0b73e94..ca7562ee9a59 100644
> --- a/gdb/or1k-linux-tdep.c
> +++ b/gdb/or1k-linux-tdep.c
> @@ -20,6 +20,7 @@
> #include "osabi.h"
> #include "glibc-tdep.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "solib-svr4.h"
> #include "regset.h"
> #include "tramp-frame.h"
> @@ -144,8 +145,7 @@ or1k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> {
> linux_init_abi (info, gdbarch, 0);
>
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c
> index 3bab0318f487..5705bd96c314 100644
> --- a/gdb/ppc-fbsd-tdep.c
> +++ b/gdb/ppc-fbsd-tdep.c
> @@ -332,8 +332,7 @@ ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> set_gdbarch_return_value (gdbarch, ppcfbsd_return_value);
>
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
>
> frame_unwind_append_unwinder (gdbarch, &ppcfbsd_sigtramp_frame_unwind);
> set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc");
> @@ -347,8 +346,7 @@ ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> ppc64_elf_make_msymbol_special);
>
> set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
> set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc");
> }
>
> diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
> index b3cc4d5485e2..8f93d468bf99 100644
> --- a/gdb/ppc-linux-tdep.c
> +++ b/gdb/ppc-linux-tdep.c
> @@ -48,6 +48,7 @@
> #include "arch-utils.h"
> #include "xml-syscall.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "svr4-tls-tdep.h"
> #include "linux-record.h"
> #include "record-full.h"
> @@ -86,8 +87,6 @@
> #include "features/rs6000/powerpc-e500l.c"
> #include "dwarf2/frame.h"
>
> -/* Shared library operations for PowerPC-Linux. */
> -static solib_ops powerpc_so_ops;
>
> /* The syscall's XML filename for PPC and PPC64. */
> #define XML_SYSCALL_FILENAME_PPC "syscalls/ppc-linux.xml"
> @@ -306,16 +305,33 @@ static const struct ppc_insn_pattern powerpc32_plt_stub_so_2[] =
> /* The max number of insns we check using ppc_insns_match_pattern. */
> #define POWERPC32_PLT_CHECK_LEN (ARRAY_SIZE (powerpc32_plt_stub) - 1)
>
> -/* Check if PC is in PLT stub. For non-secure PLT, stub is in .plt
> - section. For secure PLT, stub is in .text and we need to check
> - instruction patterns. */
> +/* solib_ops for ILP32 PowerPC/Linux systems. */
>
> -static bool
> -powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc)
> +struct ppc_linux_ilp32_svr4_solib_ops : public linux_ilp32_svr4_solib_ops
> +{
> + /* Check if PC is in PLT stub. For non-secure PLT, stub is in .plt
> + section. For secure PLT, stub is in .text and we need to check
> + instruction patterns. */
> +
> + bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
> +};
> +
> +/* Return a new solib_ops for ILP32 PowerPC/Linux systems. */
> +
> +static solib_ops_up
> +new_ppc_linux_ilp32_svr4_solib_ops ()
> +{
> + return std::make_unique<ppc_linux_ilp32_svr4_solib_ops> ();
> +}
> +
> +/* See ppc_linux_ilp32_svr4_solib_ops. */
> +
> +bool
> +ppc_linux_ilp32_svr4_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
> {
> /* Check whether PC is in the dynamic linker. This also checks
> whether it is in the .plt section, used by non-PIC executables. */
> - if (svr4_in_dynsym_resolve_code (pc))
> + if (linux_ilp32_svr4_solib_ops::in_dynsym_resolve_code (pc))
> return true;
>
> /* Check if we are in the resolver. */
> @@ -2265,8 +2281,6 @@ ppc_linux_init_abi (struct gdbarch_info info,
>
> /* Shared library handling. */
> set_gdbarch_skip_trampoline_code (gdbarch, ppc_skip_trampoline_code);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
>
> /* Setting the correct XML syscall filename. */
> set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_PPC);
> @@ -2283,14 +2297,7 @@ ppc_linux_init_abi (struct gdbarch_info info,
> else
> set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc");
>
> - if (powerpc_so_ops.in_dynsym_resolve_code == NULL)
> - {
> - powerpc_so_ops = svr4_so_ops;
> - /* Override dynamic resolve function. */
> - powerpc_so_ops.in_dynsym_resolve_code =
> - powerpc_linux_in_dynsym_resolve_code;
> - }
> - set_gdbarch_so_ops (gdbarch, &powerpc_so_ops);
> + set_solib_svr4_ops (gdbarch, new_ppc_linux_ilp32_svr4_solib_ops);
>
> set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
> }
> @@ -2317,8 +2324,7 @@ ppc_linux_init_abi (struct gdbarch_info info,
>
> /* Shared library handling. */
> set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_lp64_svr4_solib_ops);
>
> /* Setting the correct XML syscall filename. */
> set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_PPC64);
> diff --git a/gdb/ppc-netbsd-tdep.c b/gdb/ppc-netbsd-tdep.c
> index 911c012983e6..b030f93a2525 100644
> --- a/gdb/ppc-netbsd-tdep.c
> +++ b/gdb/ppc-netbsd-tdep.c
> @@ -179,8 +179,7 @@ ppcnbsd_init_abi (struct gdbarch_info info,
> set_gdbarch_return_value (gdbarch, ppcnbsd_return_value);
>
> /* NetBSD uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
>
> set_gdbarch_iterate_over_regset_sections
> (gdbarch, ppcnbsd_iterate_over_regset_sections);
> diff --git a/gdb/ppc-obsd-tdep.c b/gdb/ppc-obsd-tdep.c
> index 5e271c1c7be3..dc00227a0c29 100644
> --- a/gdb/ppc-obsd-tdep.c
> +++ b/gdb/ppc-obsd-tdep.c
> @@ -254,8 +254,7 @@ ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value);
>
> /* OpenBSD uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
>
> set_gdbarch_iterate_over_regset_sections
> (gdbarch, ppcobsd_iterate_over_regset_sections);
> diff --git a/gdb/progspace.h b/gdb/progspace.h
> index abb448195d74..c84a95c96657 100644
> --- a/gdb/progspace.h
> +++ b/gdb/progspace.h
> @@ -21,6 +21,7 @@
> #ifndef GDB_PROGSPACE_H
> #define GDB_PROGSPACE_H
>
> +#include "solib.h"
> #include "target.h"
> #include "gdb_bfd.h"
> #include "registry.h"
> @@ -234,19 +235,23 @@ struct program_space
> /* Set this program space's solib provider.
>
> The solib provider must be unset prior to call this method. */
> - void set_solib_ops (const struct solib_ops &ops)
> + void set_solib_ops (solib_ops_up ops)
> {
> gdb_assert (m_solib_ops == nullptr);
> - m_solib_ops = &ops;
> + m_solib_ops = std::move (ops);
> };
>
> - /* Unset this program space's solib provider. */
> + /* Unset and free this program space's solib provider. */
> void unset_solib_ops ()
> { m_solib_ops = nullptr; }
>
> + /* Unset and return this program space's solib provider. */
> + solib_ops_up release_solib_ops ()
> + { return std::move (m_solib_ops); }
> +
> /* Get this program space's solib provider. */
> - const struct solib_ops *solib_ops () const
> - { return m_solib_ops; }
> + struct solib_ops *solib_ops () const
> + { return m_solib_ops.get (); }
>
> /* Return the list of all the solibs in this program space. */
> owning_intrusive_list<solib> &solibs ()
> @@ -373,7 +378,7 @@ struct program_space
> owning_intrusive_list<objfile> m_objfiles_list;
>
> /* solib_ops implementation used to provide solibs in this program space. */
> - const struct solib_ops *m_solib_ops = nullptr;
> + solib_ops_up m_solib_ops;
>
> /* List of shared objects mapped into this space. Managed by
> solib.c. */
> diff --git a/gdb/riscv-fbsd-tdep.c b/gdb/riscv-fbsd-tdep.c
> index fcb91caf5fb6..69e14ac47e3a 100644
> --- a/gdb/riscv-fbsd-tdep.c
> +++ b/gdb/riscv-fbsd-tdep.c
> @@ -191,10 +191,9 @@ riscv_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> set_gdbarch_software_single_step (gdbarch, riscv_software_single_step);
>
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - (riscv_isa_xlen (gdbarch) == 4
> - ? svr4_ilp32_fetch_link_map_offsets
> - : svr4_lp64_fetch_link_map_offsets));
> + set_solib_svr4_ops (gdbarch, (riscv_isa_xlen (gdbarch) == 4
> + ? new_svr4_ilp32_solib_ops
> + : new_svr4_lp64_solib_ops));
>
> tramp_frame_prepend_unwinder (gdbarch, &riscv_fbsd_sigframe);
>
> diff --git a/gdb/riscv-linux-tdep.c b/gdb/riscv-linux-tdep.c
> index e1ea6158a45c..fb21fa0cfa1a 100644
> --- a/gdb/riscv-linux-tdep.c
> +++ b/gdb/riscv-linux-tdep.c
> @@ -20,6 +20,7 @@
> #include "osabi.h"
> #include "glibc-tdep.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "svr4-tls-tdep.h"
> #include "solib-svr4.h"
> #include "regset.h"
> @@ -512,10 +513,9 @@ riscv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> set_gdbarch_software_single_step (gdbarch, riscv_software_single_step);
>
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - (riscv_isa_xlen (gdbarch) == 4
> - ? linux_ilp32_fetch_link_map_offsets
> - : linux_lp64_fetch_link_map_offsets));
> + set_solib_svr4_ops (gdbarch, (riscv_isa_xlen (gdbarch) == 4
> + ? new_linux_ilp32_svr4_solib_ops
> + : new_linux_lp64_svr4_solib_ops));
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
> index ab9feb38fb78..214fb88c32cc 100644
> --- a/gdb/rs6000-aix-tdep.c
> +++ b/gdb/rs6000-aix-tdep.c
> @@ -1411,7 +1411,7 @@ rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
> set_gdbarch_wchar_signed (gdbarch, 0);
> set_gdbarch_auto_wide_charset (gdbarch, rs6000_aix_auto_wide_charset);
>
> - set_gdbarch_so_ops (gdbarch, &solib_aix_so_ops);
> + set_gdbarch_new_solib_ops (gdbarch, new_aix_solib_ops);
> frame_unwind_append_unwinder (gdbarch, &aix_sighandle_frame_unwind);
> }
>
> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
> index bd1f42ca8d25..e22e1454bed6 100644
> --- a/gdb/s390-linux-tdep.c
> +++ b/gdb/s390-linux-tdep.c
> @@ -29,6 +29,7 @@
> #include "gdbcore.h"
> #include "linux-record.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "svr4-tls-tdep.h"
> #include "objfiles.h"
> #include "osabi.h"
> @@ -1214,8 +1215,7 @@ s390_linux_init_abi_31 (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> s390_linux_init_abi_any (info, gdbarch);
>
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
> set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_S390);
> }
>
> @@ -1230,8 +1230,7 @@ s390_linux_init_abi_64 (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> s390_linux_init_abi_any (info, gdbarch);
>
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_lp64_svr4_solib_ops);
> set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_S390X);
> }
>
> diff --git a/gdb/sh-linux-tdep.c b/gdb/sh-linux-tdep.c
> index f0b35d3063a6..c28ec361eb05 100644
> --- a/gdb/sh-linux-tdep.c
> +++ b/gdb/sh-linux-tdep.c
> @@ -28,6 +28,7 @@
> #include "glibc-tdep.h"
> #include "sh-tdep.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "gdbarch.h"
>
> #define REGSx16(base) \
> @@ -187,8 +188,7 @@ sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
> set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
>
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> diff --git a/gdb/sh-netbsd-tdep.c b/gdb/sh-netbsd-tdep.c
> index f99566f2fd59..685ba3c0585d 100644
> --- a/gdb/sh-netbsd-tdep.c
> +++ b/gdb/sh-netbsd-tdep.c
> @@ -68,8 +68,7 @@ shnbsd_init_abi (struct gdbarch_info info,
> tdep->core_gregmap = (struct sh_corefile_regmap *)regmap;
> tdep->sizeof_gregset = 84;
>
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
> }
>
> void _initialize_shnbsd_tdep ();
> diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
> index 17eeba940770..91cc1d8c66de 100644
> --- a/gdb/solib-aix.c
> +++ b/gdb/solib-aix.c
> @@ -24,6 +24,24 @@
> #include "xcoffread.h"
> #include "observable.h"
>
> +/* solib_ops for AIX systems. */
> +
> +struct aix_solib_ops : public solib_ops
> +{
> + void relocate_section_addresses (solib &so, target_section *) const override;
> + void create_inferior_hook (int from_tty) override;
> + owning_intrusive_list<solib> current_sos () override;
> + gdb_bfd_ref_ptr bfd_open (const char *pathname) override;
> +};
> +
> +/* See solib-aix.h. */
> +
> +solib_ops_up
> +new_aix_solib_ops ()
> +{
> + return std::make_unique<aix_solib_ops> ();
> +}
> +
> /* Our private data in struct solib. */
>
> struct lm_info_aix final : public lm_info
> @@ -306,10 +324,9 @@ solib_aix_bss_data_overlap (bfd *abfd)
> return 0;
> }
>
> -/* Implement the "relocate_section_addresses" solib_ops method. */
> -
> -static void
> -solib_aix_relocate_section_addresses (solib &so, target_section *sec)
> +void
> +aix_solib_ops::relocate_section_addresses (solib &so,
> + target_section *sec) const
> {
> struct bfd_section *bfd_sect = sec->the_bfd_section;
> bfd *abfd = bfd_sect->owner;
> @@ -410,10 +427,8 @@ solib_aix_get_section_offsets (struct objfile *objfile,
> return offsets;
> }
>
> -/* Implement the "solib_create_inferior_hook" solib_ops method. */
> -
> -static void
> -solib_aix_solib_create_inferior_hook (int from_tty)
> +void
> +aix_solib_ops::create_inferior_hook (int from_tty)
> {
> const char *warning_msg = "unable to relocate main executable";
>
> @@ -441,10 +456,8 @@ solib_aix_solib_create_inferior_hook (int from_tty)
> }
> }
>
> -/* Implement the "current_sos" solib_ops method. */
> -
> -static owning_intrusive_list<solib>
> -solib_aix_current_sos ()
> +owning_intrusive_list<solib>
> +aix_solib_ops::current_sos ()
> {
> std::optional<std::vector<lm_info_aix>> &library_list
> = solib_aix_get_library_list (current_inferior (), NULL);
> @@ -480,7 +493,7 @@ solib_aix_current_sos ()
> }
>
> /* Add it to the list. */
> - auto &new_solib = sos.emplace_back (solib_aix_so_ops);
> + auto &new_solib = sos.emplace_back (*this);
> new_solib.original_name = so_name;
> new_solib.name = so_name;
> new_solib.lm_info = std::make_unique<lm_info_aix> (info);
> @@ -489,10 +502,8 @@ solib_aix_current_sos ()
> return sos;
> }
>
> -/* Implement the "bfd_open" solib_ops method. */
> -
> -static gdb_bfd_ref_ptr
> -solib_aix_bfd_open (const char *pathname)
> +gdb_bfd_ref_ptr
> +aix_solib_ops::bfd_open (const char *pathname)
> {
> /* The pathname is actually a synthetic filename with the following
> form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
> @@ -506,7 +517,7 @@ solib_aix_bfd_open (const char *pathname)
> int found_file;
>
> if (pathname[path_len - 1] != ')')
> - return solib_bfd_open (pathname);
> + return solib_ops::bfd_open (pathname);
>
> /* Search for the associated parens. */
> sep = strrchr (pathname, '(');
> @@ -516,7 +527,7 @@ solib_aix_bfd_open (const char *pathname)
> to open pathname without decoding, possibly leading to
> a failure), rather than triggering an assert failure). */
> warning (_("missing '(' in shared object pathname: %s"), pathname);
> - return solib_bfd_open (pathname);
> + return solib_ops::bfd_open (pathname);
> }
> filename_len = sep - pathname;
>
> @@ -659,24 +670,6 @@ solib_aix_normal_stop_observer (struct bpstat *unused_1, int unused_2)
> data->library_list.reset ();
> }
>
> -/* The solib_ops for AIX targets. */
> -const solib_ops solib_aix_so_ops =
> -{
> - solib_aix_relocate_section_addresses,
> - nullptr,
> - nullptr,
> - solib_aix_solib_create_inferior_hook,
> - solib_aix_current_sos,
> - nullptr,
> - nullptr,
> - solib_aix_bfd_open,
> - nullptr,
> - nullptr,
> - nullptr,
> - nullptr,
> - default_find_solib_addr,
> -};
> -
> void _initialize_solib_aix ();
> void
> _initialize_solib_aix ()
> diff --git a/gdb/solib-aix.h b/gdb/solib-aix.h
> index 7a1bc7b4b567..ac824e547cfa 100644
> --- a/gdb/solib-aix.h
> +++ b/gdb/solib-aix.h
> @@ -18,9 +18,12 @@
> #ifndef GDB_SOLIB_AIX_H
> #define GDB_SOLIB_AIX_H
>
> -struct solib_ops;
> -extern const solib_ops solib_aix_so_ops;
> +#include "solib.h"
>
> extern CORE_ADDR solib_aix_get_toc_value (CORE_ADDR pc);
>
> +/* Return a new solib_ops for AIX systems. */
> +
> +solib_ops_up new_aix_solib_ops ();
> +
> #endif /* GDB_SOLIB_AIX_H */
> diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
> index 88a2962f5dd5..aece190a711d 100644
> --- a/gdb/solib-darwin.c
> +++ b/gdb/solib-darwin.c
> @@ -33,6 +33,25 @@
> #include "mach-o.h"
> #include "mach-o/external.h"
>
> +/* solib_ops for Darwin systems. */
> +
> +struct darwin_solib_ops : public solib_ops
> +{
> + void relocate_section_addresses (solib &so, target_section *) const override;
> + void clear_solib (program_space *pspace) override;
> + void create_inferior_hook (int from_tty) override;
> + owning_intrusive_list<solib> current_sos () override;
> + gdb_bfd_ref_ptr bfd_open (const char *pathname) override;
> +};
> +
> +/* See solib-darwin.h. */
> +
> +solib_ops_up
> +new_darwin_solib_ops ()
> +{
> + return std::make_unique<darwin_solib_ops> ();
> +}
> +
> struct gdb_dyld_image_info
> {
> /* Base address (which corresponds to the Mach-O header). */
> @@ -188,10 +207,8 @@ find_program_interpreter (void)
> return buf;
> }
>
> -/* Build a list of currently loaded shared objects. See solib-svr4.c. */
> -
> -static owning_intrusive_list<solib>
> -darwin_current_sos ()
> +owning_intrusive_list<solib>
> +darwin_solib_ops::current_sos ()
> {
> type *ptr_type
> = builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
> @@ -250,7 +267,7 @@ darwin_current_sos ()
> break;
>
> /* Create and fill the new struct solib element. */
> - auto &newobj = sos.emplace_back (darwin_so_ops);
> + auto &newobj = sos.emplace_back (*this);
>
> auto li = std::make_unique<lm_info_darwin> ();
>
> @@ -457,10 +474,8 @@ darwin_solib_read_all_image_info_addr (struct darwin_info *info)
> info->all_image_addr = extract_unsigned_integer (buf, len, BFD_ENDIAN_BIG);
> }
>
> -/* Shared library startup support. See documentation in solib-svr4.c. */
> -
> -static void
> -darwin_solib_create_inferior_hook (int from_tty)
> +void
> +darwin_solib_ops::create_inferior_hook (int from_tty)
> {
> /* Everything below only makes sense if we have a running inferior. */
> if (!target_has_execution ())
> @@ -560,8 +575,8 @@ darwin_solib_create_inferior_hook (int from_tty)
> create_solib_event_breakpoint (current_inferior ()->arch (), notifier);
> }
>
> -static void
> -darwin_clear_solib (program_space *pspace)
> +void
> +darwin_solib_ops::clear_solib (program_space *pspace)
> {
> darwin_info *info = get_darwin_info (pspace);
>
> @@ -572,8 +587,9 @@ darwin_clear_solib (program_space *pspace)
> /* The section table is built from bfd sections using bfd VMAs.
> Relocate these VMAs according to solib info. */
>
> -static void
> -darwin_relocate_section_addresses (solib &so, target_section *sec)
> +void
> +darwin_solib_ops::relocate_section_addresses (solib &so,
> + target_section *sec) const
> {
> auto *li = gdb::checked_static_cast<lm_info_darwin *> (so.lm_info.get ());
>
> @@ -592,9 +608,9 @@ darwin_relocate_section_addresses (solib &so, target_section *sec)
> if (sec->addr < so.addr_low)
> so.addr_low = sec->addr;
> }
> -\f
> -static gdb_bfd_ref_ptr
> -darwin_bfd_open (const char *pathname)
> +
> +gdb_bfd_ref_ptr
> +darwin_solib_ops::bfd_open (const char *pathname)
> {
> int found_file;
>
> @@ -622,20 +638,3 @@ darwin_bfd_open (const char *pathname)
>
> return res;
> }
> -
> -const solib_ops darwin_so_ops =
> -{
> - darwin_relocate_section_addresses,
> - nullptr,
> - darwin_clear_solib,
> - darwin_solib_create_inferior_hook,
> - darwin_current_sos,
> - nullptr,
> - nullptr,
> - darwin_bfd_open,
> - nullptr,
> - nullptr,
> - nullptr,
> - nullptr,
> - default_find_solib_addr,
> -};
> diff --git a/gdb/solib-darwin.h b/gdb/solib-darwin.h
> index b96e744669fb..09dac6bf52ba 100644
> --- a/gdb/solib-darwin.h
> +++ b/gdb/solib-darwin.h
> @@ -20,8 +20,10 @@
> #ifndef GDB_SOLIB_DARWIN_H
> #define GDB_SOLIB_DARWIN_H
>
> -struct solib_ops;
> +#include "solib.h"
>
> -extern const solib_ops darwin_so_ops;
> +/* Return a new solib_ops for Darwin systems. */
> +
> +extern solib_ops_up new_darwin_solib_ops ();
>
> #endif /* GDB_SOLIB_DARWIN_H */
> diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
> index f6748b69353a..97e32d19e57d 100644
> --- a/gdb/solib-dsbt.c
> +++ b/gdb/solib-dsbt.c
> @@ -120,6 +120,25 @@ struct dbst_ext_link_map
> ext_ptr l_next, l_prev; /* struct link_map *l_next, *l_prev; */
> };
>
> +/* solib_ops for DSBT systems. */
> +
> +struct dsbt_solib_ops : public solib_ops
> +{
> + void relocate_section_addresses (solib &so, target_section *) const override;
> + void clear_solib (program_space *pspace) override;
> + void create_inferior_hook (int from_tty) override;
> + owning_intrusive_list<solib> current_sos () override;
> + bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
> +};
> +
> +/* See solib-dsbt.h. */
> +
> +solib_ops_up
> +new_dsbt_solib_ops ()
> +{
> + return std::make_unique<dsbt_solib_ops> ();
> +}
> +
> /* Link map info to include in an allocated solib entry */
>
> struct lm_info_dsbt final : public lm_info
> @@ -502,8 +521,8 @@ lm_base (void)
> themselves. The declaration of `struct solib' says which fields
> we provide values for. */
>
> -static owning_intrusive_list<solib>
> -dsbt_current_sos (void)
> +owning_intrusive_list<solib>
> +dsbt_solib_ops::current_sos ()
> {
> bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
> CORE_ADDR lm_addr;
> @@ -584,7 +603,7 @@ dsbt_current_sos (void)
> break;
> }
>
> - auto &sop = sos.emplace_back (dsbt_so_ops);
> + auto &sop = sos.emplace_back (*this);
> auto li = std::make_unique<lm_info_dsbt> ();
> li->map = loadmap;
> /* Fetch the name. */
> @@ -623,8 +642,8 @@ dsbt_current_sos (void)
> /* Return true if PC lies in the dynamic symbol resolution code of the
> run time loader. */
>
> -static bool
> -dsbt_in_dynsym_resolve_code (CORE_ADDR pc)
> +bool
> +dsbt_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
> {
> dsbt_info *info = get_dsbt_info (current_program_space);
>
> @@ -840,8 +859,8 @@ dsbt_relocate_main_executable (void)
> For the DSBT shared library, the main executable needs to be relocated.
> The shared library breakpoints also need to be enabled. */
>
> -static void
> -dsbt_solib_create_inferior_hook (int from_tty)
> +void
> +dsbt_solib_ops::create_inferior_hook (int from_tty)
> {
> /* Relocate main executable. */
> dsbt_relocate_main_executable ();
> @@ -854,8 +873,8 @@ dsbt_solib_create_inferior_hook (int from_tty)
> }
> }
>
> -static void
> -dsbt_clear_solib (program_space *pspace)
> +void
> +dsbt_solib_ops::clear_solib (program_space *pspace)
> {
> dsbt_info *info = get_dsbt_info (pspace);
>
> @@ -866,8 +885,9 @@ dsbt_clear_solib (program_space *pspace)
> info->main_executable_lm_info = NULL;
> }
>
> -static void
> -dsbt_relocate_section_addresses (solib &so, target_section *sec)
> +void
> +dsbt_solib_ops::relocate_section_addresses (solib &so,
> + target_section *sec) const
> {
> int seg;
> auto *li = gdb::checked_static_cast<lm_info_dsbt *> (so.lm_info.get ());
> @@ -893,23 +913,6 @@ show_dsbt_debug (struct ui_file *file, int from_tty,
> gdb_printf (file, _("solib-dsbt debugging is %s.\n"), value);
> }
>
> -const solib_ops dsbt_so_ops =
> -{
> - dsbt_relocate_section_addresses,
> - nullptr,
> - dsbt_clear_solib,
> - dsbt_solib_create_inferior_hook,
> - dsbt_current_sos,
> - nullptr,
> - dsbt_in_dynsym_resolve_code,
> - solib_bfd_open,
> - nullptr,
> - nullptr,
> - nullptr,
> - nullptr,
> - default_find_solib_addr,
> -};
> -
> void _initialize_dsbt_solib ();
> void
> _initialize_dsbt_solib ()
> diff --git a/gdb/solib-dsbt.h b/gdb/solib-dsbt.h
> index d5c52c69e432..47b03bba589b 100644
> --- a/gdb/solib-dsbt.h
> +++ b/gdb/solib-dsbt.h
> @@ -20,8 +20,10 @@
> #ifndef GDB_SOLIB_DSBT_H
> #define GDB_SOLIB_DSBT_H
>
> -struct solib_ops;
> +#include "solib.h"
>
> -extern const solib_ops dsbt_so_ops;
> +/* Return a new solib_ops for DSBT systems. */
> +
> +solib_ops_up new_dsbt_solib_ops ();
>
> #endif /* GDB_SOLIB_DSBT_H */
> diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c
> index 12d3140b513c..6ef83672577d 100644
> --- a/gdb/solib-frv.c
> +++ b/gdb/solib-frv.c
> @@ -26,6 +26,26 @@
> #include "elf/frv.h"
> #include "gdb_bfd.h"
> #include "inferior.h"
> +#include "solib-frv.h"
> +
> +/* solib_ops for FR-V systems. */
> +
> +struct frv_solib_ops : public solib_ops
> +{
> + void relocate_section_addresses (solib &so, target_section *) const override;
> + void clear_solib (program_space *pspace) override;
> + void create_inferior_hook (int from_tty) override;
> + owning_intrusive_list<solib> current_sos () override;
> + bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
> +};
> +
> +/* See solib-frv.h. */
> +
> +solib_ops_up
> +new_frv_solib_ops ()
> +{
> + return std::make_unique<frv_solib_ops> ();
> +}
>
> /* FR-V pointers are four bytes wide. */
> enum { FRV_PTR_SIZE = 4 };
> @@ -293,11 +313,8 @@ lm_base (void)
> return lm_base_cache;
> }
>
> -
> -/* Implement the "current_sos" solib_ops method. */
> -
> -static owning_intrusive_list<solib>
> -frv_current_sos ()
> +owning_intrusive_list<solib>
> +frv_solib_ops::current_sos ()
> {
> bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
> CORE_ADDR lm_addr, mgot;
> @@ -367,7 +384,7 @@ frv_current_sos ()
> break;
> }
>
> - auto &sop = sos.emplace_back (frv_so_ops);
> + auto &sop = sos.emplace_back (*this);
> auto li = std::make_unique<lm_info_frv> ();
> li->map = loadmap;
> li->got_value = got_addr;
> @@ -414,8 +431,8 @@ static CORE_ADDR interp_text_sect_high;
> static CORE_ADDR interp_plt_sect_low;
> static CORE_ADDR interp_plt_sect_high;
>
> -static bool
> -frv_in_dynsym_resolve_code (CORE_ADDR pc)
> +bool
> +frv_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
> {
> return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
> || (pc >= interp_plt_sect_low && pc < interp_plt_sect_high)
> @@ -776,8 +793,8 @@ frv_relocate_main_executable (void)
> to be relocated. The shared library breakpoints also need to be
> enabled. */
>
> -static void
> -frv_solib_create_inferior_hook (int from_tty)
> +void
> +frv_solib_ops::create_inferior_hook (int from_tty)
> {
> /* Relocate main executable. */
> frv_relocate_main_executable ();
> @@ -790,8 +807,8 @@ frv_solib_create_inferior_hook (int from_tty)
> }
> }
>
> -static void
> -frv_clear_solib (program_space *pspace)
> +void
> +frv_solib_ops::clear_solib (program_space *pspace)
> {
> lm_base_cache = 0;
> enable_break2_done = 0;
> @@ -801,8 +818,9 @@ frv_clear_solib (program_space *pspace)
> main_executable_lm_info = NULL;
> }
>
> -static void
> -frv_relocate_section_addresses (solib &so, target_section *sec)
> +void
> +frv_solib_ops::relocate_section_addresses (solib &so,
> + target_section *sec) const
> {
> int seg;
> auto *li = gdb::checked_static_cast<lm_info_frv *> (so.lm_info.get ());
> @@ -1063,20 +1081,3 @@ frv_fetch_objfile_link_map (struct objfile *objfile)
> /* Not found! */
> return 0;
> }
> -
> -const solib_ops frv_so_ops =
> -{
> - frv_relocate_section_addresses,
> - nullptr,
> - frv_clear_solib,
> - frv_solib_create_inferior_hook,
> - frv_current_sos,
> - nullptr,
> - frv_in_dynsym_resolve_code,
> - solib_bfd_open,
> - nullptr,
> - nullptr,
> - nullptr,
> - nullptr,
> - default_find_solib_addr,
> -};
> diff --git a/gdb/solib-frv.h b/gdb/solib-frv.h
> new file mode 100644
> index 000000000000..0f43b39cd3e5
> --- /dev/null
> +++ b/gdb/solib-frv.h
> @@ -0,0 +1,28 @@
> +/* Handle FR-V (FDPIC) shared libraries for GDB, the GNU Debugger.
> + Copyright (C) 2024 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 GDB_SOLIB_FRV_H
> +#define GDB_SOLIB_FRV_H
> +
> +#include "solib.h"
> +
> +/* Return a new solib_ops for FR-V systems. */
> +
> +solib_ops_up new_frv_solib_ops ();
> +
> +#endif /* GDB_SOLIB_FRV_H */
> diff --git a/gdb/solib-rocm.c b/gdb/solib-rocm.c
> index a3599562e795..ab7dc3e66808 100644
> --- a/gdb/solib-rocm.c
> +++ b/gdb/solib-rocm.c
> @@ -26,6 +26,7 @@
> #include "event-top.h"
> #include "gdbsupport/fileio.h"
> #include "inferior.h"
> +#include "linux-tdep.h"
> #include "observable.h"
> #include "solib.h"
> #include "solib-svr4.h"
> @@ -153,7 +154,69 @@ struct solib_info
> /* Per-inferior data key. */
> static const registry<inferior>::key<solib_info> rocm_solib_data;
>
> -static solib_ops rocm_solib_ops;
> +/* solib_ops for ROCm systems. */
> +
> +struct rocm_solib_ops : public solib_ops
> +{
> + /* HOST_OPS is the host solib_ops that rocm_solib_ops hijacks / wraps,
> + in order to provide support for ROCm code objects. */
> + explicit rocm_solib_ops (solib_ops_up host_ops)
> + : m_host_ops (std::move (host_ops))
> + {
> + }
> +
> + /* The methods implemented by rocm_solib_ops. */
> + owning_intrusive_list<solib> current_sos () override;
> + void create_inferior_hook (int from_tty) override;
> + gdb_bfd_ref_ptr bfd_open (const char *pathname) override;
> + void relocate_section_addresses (solib &so, target_section *) const override;
> + void handle_event () override;
> +
> + /* Implement the following methods just to forward the calls to the host
> + solib_ops. We currently need to implement all the methods that
> + svr4_solib_ops implements. */
> + void clear_so (const solib &so) const override
> + { return m_host_ops->clear_so (so); }
> +
> + void clear_solib (program_space *pspace) override
> + { return m_host_ops->clear_solib (pspace); }
> +
> + bool open_symbol_file_object (int from_tty) override
> + { return m_host_ops->open_symbol_file_object (from_tty); }
> +
> + bool in_dynsym_resolve_code (CORE_ADDR pc) const override
> + { return m_host_ops->in_dynsym_resolve_code (pc); }
> +
> + bool same (const solib &gdb, const solib &inferior) const override
> + { return m_host_ops->same (gdb, inferior); }
> +
> + bool keep_data_in_core (CORE_ADDR vaddr, unsigned long size) override
> + { return m_host_ops->keep_data_in_core (vaddr, size); }
> +
> + void update_breakpoints () const override
> + { return m_host_ops->update_breakpoints (); }
> +
> + std::optional<CORE_ADDR> find_solib_addr (solib &so) const override
> + { return m_host_ops->find_solib_addr (so); }
> +
> + bool supports_namespaces () const override
> + { return true; }
> +
> + int find_solib_ns (const solib &so) const override
> + { return m_host_ops->find_solib_ns (so); }
> +
> + int num_active_namespaces () const override
> + { return m_host_ops->num_active_namespaces (); }
> +
> + std::vector<const solib *> get_solibs_in_ns (int nsid) const override
> + { return m_host_ops->get_solibs_in_ns (nsid); }
> +
> +private:
> + owning_intrusive_list<solib>
> + solibs_from_rocm_sos (const std::vector<rocm_so> &sos);
> +
> + solib_ops_up m_host_ops;
> +};
>
> /* Fetch the solib_info data for INF. */
>
> @@ -170,13 +233,13 @@ get_solib_info (inferior *inf)
>
> /* Relocate section addresses. */
>
> -static void
> -rocm_solib_relocate_section_addresses (solib &so,
> - struct target_section *sec)
> +void
> +rocm_solib_ops::relocate_section_addresses (solib &so,
> + struct target_section *sec) const
> {
> if (!is_amdgpu_arch (gdbarch_from_bfd (so.abfd.get ())))
> {
> - svr4_so_ops.relocate_section_addresses (so, sec);
> + m_host_ops->relocate_section_addresses (so, sec);
> return;
> }
>
> @@ -187,30 +250,30 @@ rocm_solib_relocate_section_addresses (solib &so,
>
> static void rocm_update_solib_list ();
>
> -static void
> -rocm_solib_handle_event ()
> +void
> +rocm_solib_ops::handle_event ()
> {
> - /* Since we sit on top of svr4_so_ops, we might get called following an event
> - concerning host libraries. We must therefore forward the call. If the
> - event was for a ROCm code object, it will be a no-op. On the other hand,
> + /* Since we sit on top of a host solib_ops, we might get called following an
> + event concerning host libraries. We must therefore forward the call. If
> + the event was for a ROCm code object, it will be a no-op. On the other hand
> if the event was for host libraries, rocm_update_solib_list will be
> essentially be a no-op (it will reload the same code object list as was
> previously loaded). */
> - svr4_so_ops.handle_event ();
> + m_host_ops->handle_event ();
>
> rocm_update_solib_list ();
> }
>
> /* Create solib objects from rocm_so objects in SOS. */
>
> -static owning_intrusive_list<solib>
> -solibs_from_rocm_sos (const std::vector<rocm_so> &sos)
> +owning_intrusive_list<solib>
> +rocm_solib_ops::solibs_from_rocm_sos (const std::vector<rocm_so> &sos)
> {
> owning_intrusive_list<solib> dst;
>
> for (const rocm_so &so : sos)
> {
> - auto &newobj = dst.emplace_back (rocm_solib_ops);
> + auto &newobj = dst.emplace_back (*this);
>
> newobj.lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
> newobj.name = so.name;
> @@ -223,11 +286,11 @@ solibs_from_rocm_sos (const std::vector<rocm_so> &sos)
> /* Build a list of `struct solib' objects describing the shared
> objects currently loaded in the inferior. */
>
> -static owning_intrusive_list<solib>
> -rocm_solib_current_sos ()
> +owning_intrusive_list<solib>
> +rocm_solib_ops::current_sos ()
> {
> /* First, retrieve the host-side shared library list. */
> - owning_intrusive_list<solib> sos = svr4_so_ops.current_sos ();
> + owning_intrusive_list<solib> sos = m_host_ops->current_sos ();
>
> /* Then, the device-side shared library list. */
> std::vector<rocm_so> &dev_sos = get_solib_info (current_inferior ())->solib_list;
> @@ -579,12 +642,12 @@ rocm_bfd_iovec_open (bfd *abfd, inferior *inferior)
> }
> }
>
> -static gdb_bfd_ref_ptr
> -rocm_solib_bfd_open (const char *pathname)
> +gdb_bfd_ref_ptr
> +rocm_solib_ops::bfd_open (const char *pathname)
> {
> /* Handle regular files with SVR4 open. */
> if (strstr (pathname, "://") == nullptr)
> - return svr4_so_ops.bfd_open (pathname);
> + return m_host_ops->bfd_open (pathname);
>
> auto open = [] (bfd *nbfd) -> gdb_bfd_iovec_base *
> {
> @@ -668,12 +731,12 @@ rocm_solib_bfd_open (const char *pathname)
> return abfd;
> }
>
> -static void
> -rocm_solib_create_inferior_hook (int from_tty)
> +void
> +rocm_solib_ops::create_inferior_hook (int from_tty)
> {
> get_solib_info (current_inferior ())->solib_list.clear ();
>
> - svr4_so_ops.solib_create_inferior_hook (from_tty);
> + m_host_ops->create_inferior_hook (from_tty);
> }
>
> static void
> @@ -736,22 +799,6 @@ rocm_update_solib_list ()
>
> sos.emplace_back (uri_bytes, std::move (unique_name), std::move (li));
> }
> -
> - if (rocm_solib_ops.current_sos == NULL)
> - {
> - /* Override what we need to. */
> - rocm_solib_ops = svr4_so_ops;
> - rocm_solib_ops.current_sos = rocm_solib_current_sos;
> - rocm_solib_ops.solib_create_inferior_hook
> - = rocm_solib_create_inferior_hook;
> - rocm_solib_ops.bfd_open = rocm_solib_bfd_open;
> - rocm_solib_ops.relocate_section_addresses
> - = rocm_solib_relocate_section_addresses;
> - rocm_solib_ops.handle_event = rocm_solib_handle_event;
> -
> - /* Engage the ROCm so_ops. */
> - set_gdbarch_so_ops (current_inferior ()->arch (), &rocm_solib_ops);
> - }
> }
>
> static void
> @@ -759,6 +806,10 @@ rocm_solib_target_inferior_created (inferior *inf)
> {
> get_solib_info (inf)->solib_list.clear ();
>
> + auto prev_ops = inf->pspace->release_solib_ops ();
> + auto rocm_ops = std::make_unique<rocm_solib_ops> (std::move (prev_ops));
> + inf->pspace->set_solib_ops (std::move (rocm_ops));
> +
> rocm_update_solib_list ();
>
> /* Force GDB to reload the solibs. */
> @@ -766,6 +817,21 @@ rocm_solib_target_inferior_created (inferior *inf)
> solib_add (nullptr, 0, auto_solib_add);
> }
>
> +static void
> +rocm_solib_target_inferior_execd (inferior *exec_inf, inferior *follow_inf)
> +{
> + /* Engage the ROCm so_ops, but only if dbgapi is attached to the inferior
> + (avoiding remote inferiors and core file debugging). */
> + if (get_amd_dbgapi_process_id (follow_inf) == AMD_DBGAPI_PROCESS_NONE)
> + return;
> +
> + auto prev_ops = follow_inf->pspace->release_solib_ops ();
> + auto rocm_ops = std::make_unique<rocm_solib_ops> (std::move (prev_ops));
> + follow_inf->pspace->set_solib_ops (std::move (rocm_ops));
> +
> + get_solib_info (exec_inf)->solib_list.clear ();
> +}
> +
> /* -Wmissing-prototypes */
> extern initialize_file_ftype _initialize_rocm_solib;
>
> @@ -779,4 +845,8 @@ _initialize_rocm_solib ()
> (rocm_solib_target_inferior_created,
> "solib-rocm",
> { &get_amd_dbgapi_target_inferior_created_observer_token () });
> +
> + gdb::observers::inferior_execd.attach
> + (rocm_solib_target_inferior_execd, "solib-rocm",
> + { &get_amd_dbgapi_target_inferior_execd_observer_token () });
> }
> diff --git a/gdb/solib-svr4-linux.c b/gdb/solib-svr4-linux.c
> new file mode 100644
> index 000000000000..c4bd8d89cfab
> --- /dev/null
> +++ b/gdb/solib-svr4-linux.c
> @@ -0,0 +1,98 @@
> +/* Target-dependent code for GNU/Linux using SVR4-style libraries.
> +
> + Copyright (C) 2025 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/>. */
> +
> +#include "solib-svr4-linux.h"
> +
> +/* See solib-svr4-linux.h. */
> +
> +solib_ops_up
> +new_linux_ilp32_svr4_solib_ops ()
> +{
> + return std::make_unique<linux_ilp32_svr4_solib_ops> ();
> +}
> +
> +/* See solib-svr4-linux.h. */
> +
> +link_map_offsets *
> +linux_ilp32_svr4_solib_ops::fetch_link_map_offsets () const
> +{
> + static link_map_offsets lmo;
> + static link_map_offsets *lmp = nullptr;
> +
> + if (lmp == nullptr)
> + {
> + lmp = &lmo;
> +
> + lmo.r_version_offset = 0;
> + lmo.r_version_size = 4;
> + lmo.r_map_offset = 4;
> + lmo.r_brk_offset = 8;
> + lmo.r_ldsomap_offset = -1;
> + lmo.r_next_offset = 20;
> +
> + /* Everything we need is in the first 20 bytes. */
> + lmo.link_map_size = 20;
> + lmo.l_addr_offset = 0;
> + lmo.l_name_offset = 4;
> + lmo.l_ld_offset = 8;
> + lmo.l_next_offset = 12;
> + lmo.l_prev_offset = 16;
> + }
> +
> + return lmp;
> +}
> +
> +/* See solib-svr4-linux.h. */
> +
> +solib_ops_up
> +new_linux_lp64_svr4_solib_ops ()
> +{
> + return std::make_unique<linux_lp64_svr4_solib_ops> ();
> +}
> +
> +/* See linux-tdep.h. */
> +
> +link_map_offsets *
> +linux_lp64_svr4_solib_ops::fetch_link_map_offsets () const
> +{
> + static link_map_offsets lmo;
> + static link_map_offsets *lmp = nullptr;
> +
> + if (lmp == nullptr)
> + {
> + lmp = &lmo;
> +
> + lmo.r_version_offset = 0;
> + lmo.r_version_size = 4;
> + lmo.r_map_offset = 8;
> + lmo.r_brk_offset = 16;
> + lmo.r_ldsomap_offset = -1;
> + lmo.r_next_offset = 40;
> +
> + /* Everything we need is in the first 40 bytes. */
> + lmo.link_map_size = 40;
> + lmo.l_addr_offset = 0;
> + lmo.l_name_offset = 8;
> + lmo.l_ld_offset = 16;
> + lmo.l_next_offset = 24;
> + lmo.l_prev_offset = 32;
> + }
> +
> + return lmp;
> +}
> diff --git a/gdb/solib-svr4-linux.h b/gdb/solib-svr4-linux.h
> new file mode 100644
> index 000000000000..885785fdfcba
> --- /dev/null
> +++ b/gdb/solib-svr4-linux.h
> @@ -0,0 +1,47 @@
> +/* Target-dependent code for GNU/Linux using SVR4-style libraries.
> +
> + Copyright (C) 2025 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 GDB_SOLIB_SVR4_LINUX_H
> +#define GDB_SOLIB_SVR4_LINUX_H
> +
> +#include "solib-svr4.h"
> +
> +/* solib_ops for ILP32 Linux systems. */
> +
> +struct linux_ilp32_svr4_solib_ops : public svr4_solib_ops
> +{
> + link_map_offsets *fetch_link_map_offsets () const override;
> +};
> +
> +/* solib_ops for LP64 Linux systems. */
> +
> +struct linux_lp64_svr4_solib_ops : public svr4_solib_ops
> +{
> + link_map_offsets *fetch_link_map_offsets () const override;
> +};
> +
> +/* Return a new solib_ops for ILP32 Linux systems. */
> +
> +extern solib_ops_up new_linux_ilp32_svr4_solib_ops ();
> +
> +/* Return a new solib_ops for LP64 Linux systems. */
> +
> +extern solib_ops_up new_linux_lp64_svr4_solib_ops ();
> +
> +#endif /* GDB_SOLIB_SVR4_LINUX_H */
> diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
> index deefc2578599..e9430281bca0 100644
> --- a/gdb/solib-svr4.c
> +++ b/gdb/solib-svr4.c
> @@ -47,7 +47,6 @@
>
> #include <map>
>
> -static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
> 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
> @@ -89,27 +88,6 @@ static const char * const main_name_list[] =
> NULL
> };
>
> -/* What to do when a probe stop occurs. */
> -
> -enum probe_action
> -{
> - /* Something went seriously wrong. Stop using probes and
> - revert to using the older interface. */
> - PROBES_INTERFACE_FAILED,
> -
> - /* No action is required. The shared object list is still
> - valid. */
> - DO_NOTHING,
> -
> - /* The shared object list should be reloaded entirely. */
> - FULL_RELOAD,
> -
> - /* Attempt to incrementally update the shared object list. If
> - the update fails or is not possible, fall back to reloading
> - the list in full. */
> - UPDATE_OR_RELOAD,
> -};
> -
> /* A probe's name and its associated action. */
>
> struct probe_info
> @@ -184,8 +162,8 @@ svr4_same (const char *gdb_name, const char *inferior_name,
> return gdb_lm_info.l_addr_inferior == inferior_lm_info.l_addr_inferior;
> }
>
> -static int
> -svr4_same (const solib &gdb, const solib &inferior)
> +bool
> +svr4_solib_ops::same (const solib &gdb, const solib &inferior) const
> {
> auto *lmg
> = gdb::checked_static_cast<const lm_info_svr4 *> (gdb.lm_info.get ());
> @@ -196,10 +174,10 @@ svr4_same (const solib &gdb, const solib &inferior)
> inferior.original_name.c_str (), *lmg, *lmi);
> }
>
> -static lm_info_svr4_up
> -lm_info_read (CORE_ADDR lm_addr)
> +lm_info_svr4_up
> +svr4_solib_ops::read_lm_info (CORE_ADDR lm_addr) const
> {
> - struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
> + link_map_offsets *lmo = this->fetch_link_map_offsets ();
> lm_info_svr4_up lm_info;
>
> gdb::byte_vector lm (lmo->link_map_size);
> @@ -229,16 +207,16 @@ lm_info_read (CORE_ADDR lm_addr)
> return lm_info;
> }
>
> -static int
> -has_lm_dynamic_from_link_map (void)
> +int
> +svr4_solib_ops::has_lm_dynamic_from_link_map () const
> {
> - struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
> + link_map_offsets *lmo = this->fetch_link_map_offsets ();
>
> return lmo->l_ld_offset >= 0;
> }
>
> -static CORE_ADDR
> -lm_addr_check (const solib &so, bfd *abfd)
> +CORE_ADDR
> +svr4_solib_ops::lm_addr_check (const solib &so, bfd *abfd) const
> {
> auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
>
> @@ -249,7 +227,7 @@ lm_addr_check (const solib &so, bfd *abfd)
>
> l_addr = li->l_addr_inferior;
>
> - if (! abfd || ! has_lm_dynamic_from_link_map ())
> + if (!abfd || !this->has_lm_dynamic_from_link_map ())
> goto set_addr;
>
> l_dynaddr = li->l_ld;
> @@ -475,8 +453,8 @@ svr4_is_default_namespace (const svr4_info *info, CORE_ADDR debug_base)
>
> /* Free the probes table. */
>
> -static void
> -free_probes_table (struct svr4_info *info)
> +void
> +svr4_solib_ops::free_probes_table (svr4_info *info) const
> {
> info->probes_table.reset (nullptr);
> }
> @@ -820,10 +798,10 @@ elf_locate_base (void)
> checking r_version for a known version number, or r_state for
> RT_CONSISTENT. */
>
> -static CORE_ADDR
> -solib_svr4_r_map (CORE_ADDR debug_base)
> +CORE_ADDR
> +svr4_solib_ops::read_r_map (CORE_ADDR debug_base) const
> {
> - struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
> + link_map_offsets *lmo = this->fetch_link_map_offsets ();
> type *ptr_type
> = builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
> CORE_ADDR addr = 0;
> @@ -843,10 +821,10 @@ solib_svr4_r_map (CORE_ADDR debug_base)
>
> /* Find r_brk from the inferior's debug base. */
>
> -static CORE_ADDR
> -solib_svr4_r_brk (struct svr4_info *info)
> +CORE_ADDR
> +svr4_solib_ops::find_r_brk (svr4_info *info) const
> {
> - struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
> + link_map_offsets *lmo = this->fetch_link_map_offsets ();
> type *ptr_type
> = builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
>
> @@ -857,10 +835,10 @@ solib_svr4_r_brk (struct svr4_info *info)
> /* Find the link map for the dynamic linker (if it is not in the
> normal list of loaded shared objects). */
>
> -static CORE_ADDR
> -solib_svr4_r_ldsomap (struct svr4_info *info)
> +CORE_ADDR
> +svr4_solib_ops::find_r_ldsomap (svr4_info *info) const
> {
> - struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
> + link_map_offsets *lmo = this->fetch_link_map_offsets ();
> type *ptr_type
> = builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
> enum bfd_endian byte_order = type_byte_order (ptr_type);
> @@ -888,10 +866,10 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
>
> /* Find the next namespace from the r_next field. */
>
> -static CORE_ADDR
> -solib_svr4_r_next (CORE_ADDR debug_base)
> +CORE_ADDR
> +svr4_solib_ops::read_r_next (CORE_ADDR debug_base) const
> {
> - link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
> + link_map_offsets *lmo = this->fetch_link_map_offsets ();
> type *ptr_type
> = builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
> bfd_endian byte_order = type_byte_order (ptr_type);
> @@ -923,8 +901,8 @@ solib_svr4_r_next (CORE_ADDR debug_base)
> memory areas containing the l_name string are saved in the core
> file. */
>
> -static int
> -svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
> +bool
> +svr4_solib_ops::keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
> {
> struct svr4_info *info;
> CORE_ADDR ldsomap;
> @@ -934,13 +912,13 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
>
> info->debug_base = elf_locate_base ();
> if (info->debug_base == 0)
> - return 0;
> + return false;
>
> - ldsomap = solib_svr4_r_ldsomap (info);
> + ldsomap = this->find_r_ldsomap (info);
> if (!ldsomap)
> - return 0;
> + return false;
>
> - std::unique_ptr<lm_info_svr4> li = lm_info_read (ldsomap);
> + std::unique_ptr<lm_info_svr4> li = this->read_lm_info (ldsomap);
> name_lm = li != NULL ? li->l_name : 0;
>
> return (name_lm >= vaddr && name_lm < vaddr + size);
> @@ -948,11 +926,11 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
>
> /* See solib.h. */
>
> -static int
> -open_symbol_file_object (int from_tty)
> +bool
> +svr4_solib_ops::open_symbol_file_object (int from_tty)
> {
> CORE_ADDR lm, l_name;
> - struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
> + link_map_offsets *lmo = this->fetch_link_map_offsets ();
> type *ptr_type
> = builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
> int l_name_size = ptr_type->length ();
> @@ -965,17 +943,17 @@ open_symbol_file_object (int from_tty)
>
> if (current_program_space->symfile_object_file)
> if (!query (_("Attempt to reload symbols from process? ")))
> - return 0;
> + return false;
>
> /* Always locate the debug struct, in case it has moved. */
> info->debug_base = elf_locate_base ();
> if (info->debug_base == 0)
> - return 0; /* failed somehow... */
> + return false; /* failed somehow... */
>
> /* First link map member should be the executable. */
> - lm = solib_svr4_r_map (info->debug_base);
> + lm = this->read_r_map (info->debug_base);
> if (lm == 0)
> - return 0; /* failed somehow... */
> + return false; /* failed somehow... */
>
> /* Read address of name from target memory to GDB. */
> read_memory (lm + lmo->l_name_offset, l_name_buf.data (), l_name_size);
> @@ -984,7 +962,7 @@ open_symbol_file_object (int from_tty)
> l_name = extract_typed_address (l_name_buf.data (), ptr_type);
>
> if (l_name == 0)
> - return 0; /* No filename. */
> + return false; /* No filename. */
>
> /* Now fetch the filename from target memory. */
> gdb::unique_xmalloc_ptr<char> filename
> @@ -993,13 +971,13 @@ open_symbol_file_object (int from_tty)
> if (filename == nullptr)
> {
> warning (_("failed to read exec filename from attached file"));
> - return 0;
> + return false;
> }
>
> /* Have a pathname: read the symbol file. */
> symbol_file_add_main (filename.get (), add_flags);
>
> - return 1;
> + return true;
> }
>
> /* Data exchange structure for the XML parser as returned by
> @@ -1032,8 +1010,8 @@ svr4_free_objfile_observer (struct objfile *objfile)
>
> /* Implement solib_ops.clear_so. */
>
> -static void
> -svr4_clear_so (const solib &so)
> +void
> +svr4_solib_ops::clear_so (const solib &so) const
> {
> auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
>
> @@ -1043,14 +1021,14 @@ svr4_clear_so (const solib &so)
>
> /* Create the solib objects equivalent to the svr4_sos in SOS. */
>
> -static owning_intrusive_list<solib>
> -solib_from_svr4_sos (const std::vector<svr4_so> &sos)
> +owning_intrusive_list<solib>
> +svr4_solib_ops::solibs_from_svr4_sos (const std::vector<svr4_so> &sos)
> {
> owning_intrusive_list<solib> dst;
>
> for (const svr4_so &so : sos)
> {
> - auto &newobj = dst.emplace_back (svr4_so_ops);
> + auto &newobj = dst.emplace_back (*this);
>
> newobj.name = so.name;
> newobj.original_name = so.name;
> @@ -1237,8 +1215,8 @@ svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
> /* If no shared library information is available from the dynamic
> linker, build a fallback list from other sources. */
>
> -static owning_intrusive_list<solib>
> -svr4_default_sos (svr4_info *info)
> +owning_intrusive_list<solib>
> +svr4_solib_ops::default_sos (svr4_info *info)
> {
> if (!info->debug_loader_offset_p)
> return {};
> @@ -1250,7 +1228,7 @@ svr4_default_sos (svr4_info *info)
> li->l_addr_p = 1;
>
> owning_intrusive_list<solib> sos;
> - auto &newobj = sos.emplace_back (svr4_so_ops);
> + auto &newobj = sos.emplace_back (*this);
>
> newobj.lm_info = std::move (li);
> newobj.name = info->debug_loader_name;
> @@ -1266,16 +1244,16 @@ svr4_default_sos (svr4_info *info)
> is returned the entries stored to LINK_PTR_PTR are still valid although they may
> represent only part of the inferior library list. */
>
> -static int
> -svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
> - std::vector<svr4_so> &sos, int ignore_first)
> +int
> +svr4_solib_ops::read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
> + std::vector<svr4_so> &sos, int ignore_first) const
> {
> CORE_ADDR first_l_name = 0;
> CORE_ADDR next_lm;
>
> for (; lm != 0; prev_lm = lm, lm = next_lm)
> {
> - lm_info_svr4_up li = lm_info_read (lm);
> + lm_info_svr4_up li = this->read_lm_info (lm);
> if (li == NULL)
> return 0;
>
> @@ -1331,8 +1309,8 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
> stored by the probes interface. Handle special cases relating
> to the first elements of the list in default namespace. */
>
> -static void
> -svr4_current_sos_direct (struct svr4_info *info)
> +void
> +svr4_solib_ops::current_sos_direct (svr4_info *info) const
> {
> CORE_ADDR lm;
> bool ignore_first;
> @@ -1398,15 +1376,15 @@ svr4_current_sos_direct (struct svr4_info *info)
> /* Collect the sos in each namespace. */
> CORE_ADDR debug_base = info->debug_base;
> for (; debug_base != 0;
> - ignore_first = false, debug_base = solib_svr4_r_next (debug_base))
> + ignore_first = false, debug_base = this->read_r_next (debug_base))
> {
> /* Walk the inferior's link map list, and build our so_list list. */
> - lm = solib_svr4_r_map (debug_base);
> + lm = this->read_r_map (debug_base);
> if (lm != 0)
> {
> svr4_maybe_add_namespace (info, debug_base);
> - svr4_read_so_list (info, lm, 0, info->solib_lists[debug_base],
> - ignore_first);
> + this->read_so_list (info, lm, 0, info->solib_lists[debug_base],
> + ignore_first);
> }
> }
>
> @@ -1419,15 +1397,15 @@ svr4_current_sos_direct (struct svr4_info *info)
> r_debug object. If we added it to the default namespace (as it was),
> we would probably run into inconsistencies with the load map's
> prev/next links (I wonder if we did). */
> - debug_base = solib_svr4_r_ldsomap (info);
> + debug_base = this->find_r_ldsomap (info);
> if (debug_base != 0)
> {
> /* Add the dynamic linker's namespace unless we already did. */
> if (info->solib_lists.find (debug_base) == info->solib_lists.end ())
> {
> svr4_maybe_add_namespace (info, debug_base);
> - svr4_read_so_list (info, debug_base, 0, info->solib_lists[debug_base],
> - 0);
> + this->read_so_list (info, debug_base, 0,
> + info->solib_lists[debug_base], 0);
> }
> }
>
> @@ -1436,15 +1414,15 @@ svr4_current_sos_direct (struct svr4_info *info)
>
> /* Collect sos read and stored by the probes interface. */
>
> -static owning_intrusive_list<solib>
> -svr4_collect_probes_sos (svr4_info *info)
> +owning_intrusive_list<solib>
> +svr4_solib_ops::collect_probes_sos (svr4_info *info)
> {
> owning_intrusive_list<solib> res;
>
> for (const auto &tuple : info->solib_lists)
> {
> const std::vector<svr4_so> &sos = tuple.second;
> - res.splice (solib_from_svr4_sos (sos));
> + res.splice (this->solibs_from_svr4_sos (sos));
> }
>
> return res;
> @@ -1453,26 +1431,26 @@ svr4_collect_probes_sos (svr4_info *info)
> /* Implement the main part of the "current_sos" solib_ops
> method. */
>
> -static owning_intrusive_list<solib>
> -svr4_current_sos_1 (svr4_info *info)
> +owning_intrusive_list<solib>
> +svr4_solib_ops::current_sos_1 (svr4_info *info)
> {
> owning_intrusive_list<solib> sos;
>
> /* If we're using the probes interface, we can use the cache as it will
> be maintained by probe update/reload actions. */
> if (info->probes_table != nullptr)
> - sos = svr4_collect_probes_sos (info);
> + sos = this->collect_probes_sos (info);
>
> /* If we're not using the probes interface or if we didn't cache
> anything, read the sos to fill the cache, then collect them from the
> cache. */
> if (sos.empty ())
> {
> - svr4_current_sos_direct (info);
> + this->current_sos_direct (info);
>
> - sos = svr4_collect_probes_sos (info);
> + sos = this->collect_probes_sos (info);
> if (sos.empty ())
> - sos = svr4_default_sos (info);
> + sos = this->default_sos (info);
> }
>
> return sos;
> @@ -1480,11 +1458,11 @@ svr4_current_sos_1 (svr4_info *info)
>
> /* Implement the "current_sos" solib_ops method. */
>
> -static owning_intrusive_list<solib>
> -svr4_current_sos ()
> +owning_intrusive_list<solib>
> +svr4_solib_ops::current_sos ()
> {
> svr4_info *info = get_svr4_info (current_program_space);
> - owning_intrusive_list<solib> sos = svr4_current_sos_1 (info);
> + owning_intrusive_list<solib> sos = this->current_sos_1 (info);
> struct mem_range vsyscall_range;
>
> /* Filter out the vDSO module, if present. Its symbol file would
> @@ -1731,7 +1709,11 @@ tls_maybe_fill_slot (solib &so)
> {
> /* Cause svr4_current_sos() to be run if it hasn't been already. */
> if (info->main_lm_addr == 0)
> - svr4_current_sos_direct (info);
> + {
> + auto &ops
> + = gdb::checked_static_cast<svr4_solib_ops &> (so.ops ());
> + ops.current_sos_direct (info);
> + }
>
> /* Quit early when main_lm_addr is still 0. */
> if (info->main_lm_addr == 0)
> @@ -1802,7 +1784,7 @@ match_main (const char *soname)
> SVR4 run time loader. */
>
> bool
> -svr4_in_dynsym_resolve_code (CORE_ADDR pc)
> +svr4_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
> {
> struct svr4_info *info = get_svr4_info (current_program_space);
>
> @@ -2001,12 +1983,10 @@ solib_event_probe_action (struct probe_and_action *pa)
> shared objects from the inferior. Handle special cases relating
> to the first elements of the list. Returns nonzero on success. */
>
> -static int
> -solist_update_full (struct svr4_info *info)
> +void
> +svr4_solib_ops::update_full (svr4_info *info) const
> {
> - svr4_current_sos_direct (info);
> -
> - return 1;
> + this->current_sos_direct (info);
> }
>
> /* Update the shared object list starting from the link-map entry
> @@ -2014,9 +1994,9 @@ solist_update_full (struct svr4_info *info)
> nonzero if the list was successfully updated, or zero to indicate
> failure. */
>
> -static int
> -solist_update_incremental (svr4_info *info, CORE_ADDR debug_base,
> - CORE_ADDR lm)
> +int
> +svr4_solib_ops::update_incremental (svr4_info *info, CORE_ADDR debug_base,
> + CORE_ADDR lm) const
> {
> /* Fall back to a full update if we are using a remote target
> that does not support incremental transfers. */
> @@ -2094,7 +2074,7 @@ solist_update_incremental (svr4_info *info, CORE_ADDR debug_base,
> above check and deferral to solist_update_full ensures
> that this call to svr4_read_so_list will never see the
> first element. */
> - if (!svr4_read_so_list (info, lm, prev_lm, solist, 0))
> + if (!this->read_so_list (info, lm, prev_lm, solist, 0))
> return 0;
> }
>
> @@ -2105,8 +2085,8 @@ solist_update_incremental (svr4_info *info, CORE_ADDR debug_base,
> original interface. We don't reset the breakpoints as the
> ones set up for the probes-based interface are adequate. */
>
> -static void
> -disable_probes_interface (svr4_info *info)
> +void
> +svr4_solib_ops::disable_probes_interface (svr4_info *info) const
> {
> warning (_("Probes-based dynamic linker interface failed.\n"
> "Reverting to original interface."));
> @@ -2121,8 +2101,8 @@ disable_probes_interface (svr4_info *info)
> probes-based linker interface. Do nothing if using the
> standard interface. */
>
> -static void
> -svr4_handle_solib_event (void)
> +void
> +svr4_solib_ops::handle_event ()
> {
> struct svr4_info *info = get_svr4_info (current_program_space);
> struct probe_and_action *pa;
> @@ -2147,9 +2127,9 @@ svr4_handle_solib_event (void)
>
> /* If anything goes wrong we revert to the original linker
> interface. */
> - auto cleanup = make_scope_exit ([info] ()
> + auto cleanup = make_scope_exit ([this, info] ()
> {
> - disable_probes_interface (info);
> + this->disable_probes_interface (info);
> });
>
> action = solib_event_probe_action (pa);
> @@ -2251,15 +2231,12 @@ svr4_handle_solib_event (void)
>
> if (action == UPDATE_OR_RELOAD)
> {
> - if (!solist_update_incremental (info, debug_base, lm))
> + if (!this->update_incremental (info, debug_base, lm))
> action = FULL_RELOAD;
> }
>
> if (action == FULL_RELOAD)
> - {
> - if (!solist_update_full (info))
> - return;
> - }
> + this->update_full (info);
>
> cleanup.release ();
> }
> @@ -2306,8 +2283,8 @@ svr4_update_solib_event_breakpoint (struct breakpoint *b)
> /* Enable or disable optional solib event breakpoints as appropriate.
> Called whenever stop_on_solib_events is changed. */
>
> -static void
> -svr4_update_solib_event_breakpoints (void)
> +void
> +svr4_solib_ops::update_breakpoints () const
> {
> for (breakpoint &bp : all_breakpoints_safe ())
> svr4_update_solib_event_breakpoint (&bp);
> @@ -2318,10 +2295,10 @@ svr4_update_solib_event_breakpoints (void)
> solib event breakpoint will be created and registered for each
> probe. */
>
> -static void
> -svr4_create_probe_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
> - const std::vector<probe *> *probes,
> - struct objfile *objfile)
> +void
> +svr4_solib_ops::create_probe_breakpoints (svr4_info *info, gdbarch *gdbarch,
> + const std::vector<probe *> *probes,
> + objfile *objfile) const
> {
> for (int i = 0; i < NUM_PROBES; i++)
> {
> @@ -2339,17 +2316,17 @@ svr4_create_probe_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
> }
> }
>
> - svr4_update_solib_event_breakpoints ();
> + this->update_breakpoints ();
> }
>
> /* Find all the glibc named probes. Only if all of the probes are found, then
> create them and return true. Otherwise return false. If WITH_PREFIX is set
> then add "rtld" to the front of the probe names. */
> -static bool
> -svr4_find_and_create_probe_breakpoints (svr4_info *info,
> - struct gdbarch *gdbarch,
> - struct obj_section *os,
> - bool with_prefix)
> +bool
> +svr4_solib_ops::find_and_create_probe_breakpoints (svr4_info *info,
> + gdbarch *gdbarch,
> + obj_section *os,
> + bool with_prefix) const
> {
> SOLIB_SCOPED_DEBUG_START_END ("objfile=%s, with_prefix=%d",
> os->objfile->original_name, with_prefix);
> @@ -2427,7 +2404,7 @@ svr4_find_and_create_probe_breakpoints (svr4_info *info,
>
> /* All probes found. Now create them. */
> solib_debug_printf ("using probes interface");
> - svr4_create_probe_breakpoints (info, gdbarch, probes, os->objfile);
> + this->create_probe_breakpoints (info, gdbarch, probes, os->objfile);
> return true;
> }
>
> @@ -2443,15 +2420,16 @@ svr4_find_and_create_probe_breakpoints (svr4_info *info,
> probes aren't found, a single breakpoint is set on the original
> marker function. */
>
> -static void
> -svr4_create_solib_event_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
> - CORE_ADDR address)
> +void
> +svr4_solib_ops::create_event_breakpoints (svr4_info *info, gdbarch *gdbarch,
> + CORE_ADDR address) const
> {
> struct obj_section *os = find_pc_section (address);
>
> if (os == nullptr
> - || (!svr4_find_and_create_probe_breakpoints (info, gdbarch, os, false)
> - && !svr4_find_and_create_probe_breakpoints (info, gdbarch, os, true)))
> + || (!this->find_and_create_probe_breakpoints (info, gdbarch, os, false)
> + && !this->find_and_create_probe_breakpoints (info, gdbarch, os,
> + true)))
> {
> solib_debug_printf ("falling back to r_brk breakpoint: addr=%s",
> paddress (gdbarch, address));
> @@ -2491,8 +2469,8 @@ svr4_create_solib_event_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
> depending upon whether or not the library is being mapped or unmapped,
> and then set to RT_CONSISTENT after the library is mapped/unmapped. */
>
> -static int
> -enable_break (struct svr4_info *info, int from_tty)
> +int
> +svr4_solib_ops::enable_break (svr4_info *info, int from_tty) const
> {
> const char * const *bkpt_namep;
> asection *interp_sect;
> @@ -2508,8 +2486,8 @@ enable_break (struct svr4_info *info, int from_tty)
>
> solib_add (NULL, from_tty, auto_solib_add);
> sym_addr = 0;
> - if (info->debug_base && solib_svr4_r_map (info->debug_base) != 0)
> - sym_addr = solib_svr4_r_brk (info);
> + if (info->debug_base && this->read_r_map (info->debug_base) != 0)
> + sym_addr = this->find_r_brk (info);
>
> if (sym_addr != 0)
> {
> @@ -2568,8 +2546,8 @@ enable_break (struct svr4_info *info, int from_tty)
> = info->interp_plt_sect_low + bfd_section_size (interp_sect);
> }
>
> - svr4_create_solib_event_breakpoints
> - (info, current_inferior ()->arch (), sym_addr);
> + this->create_event_breakpoints (info, current_inferior ()->arch (),
> + sym_addr);
> return 1;
> }
> }
> @@ -2621,7 +2599,7 @@ enable_break (struct svr4_info *info, int from_tty)
> {
> load_addr_found = 1;
> loader_found_in_list = 1;
> - load_addr = lm_addr_check (so, tmp_bfd.get ());
> + load_addr = this->lm_addr_check (so, tmp_bfd.get ());
> break;
> }
> }
> @@ -2728,9 +2706,8 @@ enable_break (struct svr4_info *info, int from_tty)
>
> if (sym_addr != 0)
> {
> - svr4_create_solib_event_breakpoints (info,
> - current_inferior ()->arch (),
> - load_addr + sym_addr);
> + this->create_event_breakpoints (info, current_inferior ()->arch (),
> + load_addr + sym_addr);
> return 1;
> }
>
> @@ -2757,9 +2734,8 @@ enable_break (struct svr4_info *info, int from_tty)
> sym_addr = gdbarch_convert_from_func_ptr_addr
> (current_inferior ()->arch (), sym_addr,
> current_inferior ()->top_target ());
> - svr4_create_solib_event_breakpoints (info,
> - current_inferior ()->arch (),
> - sym_addr);
> + this->create_event_breakpoints (info, current_inferior ()->arch (),
> + sym_addr);
> return 1;
> }
> }
> @@ -2777,8 +2753,9 @@ enable_break (struct svr4_info *info, int from_tty)
> sym_addr = gdbarch_convert_from_func_ptr_addr
> (current_inferior ()->arch (), sym_addr,
> current_inferior ()->top_target ());
> - svr4_create_solib_event_breakpoints
> - (info, current_inferior ()->arch (), sym_addr);
> + this->create_event_breakpoints (info,
> + current_inferior ()->arch (),
> + sym_addr);
> return 1;
> }
> }
> @@ -3302,15 +3279,15 @@ svr4_relocate_main_executable (void)
> addresses, and saving sufficient information about them to allow
> their symbols to be read at a later time. */
>
> -static void
> -svr4_solib_create_inferior_hook (int from_tty)
> +void
> +svr4_solib_ops::create_inferior_hook (int from_tty)
> {
> struct svr4_info *info;
>
> info = get_svr4_info (current_program_space);
>
> /* Clear the probes-based interface's state. */
> - free_probes_table (info);
> + this->free_probes_table (info);
> info->solib_lists.clear ();
> info->namespace_id.clear ();
> info->active_namespaces.clear ();
> @@ -3323,12 +3300,12 @@ svr4_solib_create_inferior_hook (int from_tty)
> if (!target_has_execution ())
> return;
>
> - if (!enable_break (info, from_tty))
> + if (!this->enable_break (info, from_tty))
> return;
> }
>
> -static void
> -svr4_clear_solib (program_space *pspace)
> +void
> +svr4_solib_ops::clear_solib (program_space *pspace)
> {
> svr4_info *info = get_svr4_info (pspace);
> info->debug_base = 0;
> @@ -3391,15 +3368,15 @@ find_loadable_elf_internal_phdr (bfd *abfd, bfd_section *asect)
> return nullptr;
> }
>
> -/* Implement solib_ops::relocate_section_addresses() for svr4 targets. */
> -
> -static void
> -svr4_relocate_section_addresses (solib &so, target_section *sec)
> +void
> +svr4_solib_ops::relocate_section_addresses (solib &so,
> + target_section *sec) const
> {
> bfd *abfd = sec->the_bfd_section->owner;
>
> - sec->addr = svr4_truncate_ptr (sec->addr + lm_addr_check (so, abfd));
> - sec->endaddr = svr4_truncate_ptr (sec->endaddr + lm_addr_check (so, abfd));
> + sec->addr = svr4_truncate_ptr (sec->addr + this->lm_addr_check (so, abfd));
> + sec->endaddr
> + = svr4_truncate_ptr (sec->endaddr + this->lm_addr_check (so, abfd));
>
> struct bfd_section *asect = sec->the_bfd_section;
> gdb_assert (asect != nullptr);
> @@ -3469,56 +3446,23 @@ svr4_relocate_section_addresses (solib &so, target_section *sec)
> }
> }
> }
> -\f
>
> -/* Architecture-specific operations. */
> -
> -struct solib_svr4_ops
> -{
> - /* Return a description of the layout of `struct link_map'. */
> - struct link_map_offsets *(*fetch_link_map_offsets)(void) = nullptr;
> -};
> -
> -/* Per-architecture data key. */
> -static const registry<gdbarch>::key<struct solib_svr4_ops> solib_svr4_data;
> -
> -/* Return a default for the architecture-specific operations. */
> -
> -static struct solib_svr4_ops *
> -get_ops (struct gdbarch *gdbarch)
> -{
> - struct solib_svr4_ops *ops = solib_svr4_data.get (gdbarch);
> - if (ops == nullptr)
> - ops = solib_svr4_data.emplace (gdbarch);
> - return ops;
> -}
> -
> -/* Set the architecture-specific `struct link_map_offsets' fetcher for
> - GDBARCH to FLMO. Also, install SVR4 solib_ops into GDBARCH. */
> +/* See solib-svr4.h. */
>
> void
> -set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
> - struct link_map_offsets *(*flmo) (void))
> +set_solib_svr4_ops (gdbarch *gdbarch, gdbarch_new_solib_ops_ftype new_solib_ops)
> {
> - struct solib_svr4_ops *ops = get_ops (gdbarch);
> -
> - ops->fetch_link_map_offsets = flmo;
> -
> - set_gdbarch_so_ops (gdbarch, &svr4_so_ops);
> + set_gdbarch_new_solib_ops (gdbarch, new_solib_ops);
> set_gdbarch_iterate_over_objfiles_in_search_order
> (gdbarch, svr4_iterate_over_objfiles_in_search_order);
> }
>
> -/* Fetch a link_map_offsets structure using the architecture-specific
> - `struct link_map_offsets' fetcher. */
> +/* See solib-svr4.h. */
>
> -static struct link_map_offsets *
> -svr4_fetch_link_map_offsets (void)
> +solib_ops_up
> +new_svr4_ilp32_solib_ops ()
> {
> - struct solib_svr4_ops *ops = get_ops (current_inferior ()->arch ());
> -
> - gdb_assert (ops->fetch_link_map_offsets);
> - return ops->fetch_link_map_offsets ();
> + return std::make_unique<ilp32_svr4_solib_ops> ();
> }
>
> /* Most OS'es that have SVR4-style ELF dynamic libraries define a
> @@ -3528,8 +3472,8 @@ svr4_fetch_link_map_offsets (void)
> /* Fetch (and possibly build) an appropriate `struct link_map_offsets'
> for an ILP32 SVR4 system. */
>
> -struct link_map_offsets *
> -svr4_ilp32_fetch_link_map_offsets (void)
> +link_map_offsets *
> +ilp32_svr4_solib_ops::fetch_link_map_offsets () const
> {
> static struct link_map_offsets lmo;
> static struct link_map_offsets *lmp = NULL;
> @@ -3557,11 +3501,26 @@ svr4_ilp32_fetch_link_map_offsets (void)
> return lmp;
> }
>
> +/* solib_ops for LP64 SVR4 systems. */
> +
> +struct lp64_svr4_solib_ops : public svr4_solib_ops
> +{
> + link_map_offsets *fetch_link_map_offsets () const override;
> +};
> +
> +/* See solib-svr4.h. */
> +
> +solib_ops_up
> +new_svr4_lp64_solib_ops ()
> +{
> + return std::make_unique<lp64_svr4_solib_ops> ();
> +}
> +
> /* Fetch (and possibly build) an appropriate `struct link_map_offsets'
> for an LP64 SVR4 system. */
>
> -struct link_map_offsets *
> -svr4_lp64_fetch_link_map_offsets (void)
> +link_map_offsets *
> +lp64_svr4_solib_ops::fetch_link_map_offsets () const
> {
> static struct link_map_offsets lmo;
> static struct link_map_offsets *lmp = NULL;
> @@ -3708,19 +3667,15 @@ svr4_iterate_over_objfiles_in_search_order
> }
> }
>
> -/* See solib_ops::find_solib_addr in solist.h. */
> -
> -static std::optional<CORE_ADDR>
> -svr4_find_solib_addr (solib &so)
> +std::optional<CORE_ADDR>
> +svr4_solib_ops::find_solib_addr (solib &so) const
> {
> auto *li = gdb::checked_static_cast<lm_info_svr4 *> (so.lm_info.get ());
> return li->l_addr_inferior;
> }
>
> -/* See solib_ops::find_solib_ns in solist.h. */
> -
> -static int
> -svr4_find_solib_ns (const solib &so)
> +int
> +svr4_solib_ops::find_solib_ns (const solib &so) const
> {
> CORE_ADDR debug_base = find_debug_base_for_solib (&so);
> svr4_info *info = get_svr4_info (current_program_space);
> @@ -3735,17 +3690,15 @@ svr4_find_solib_ns (const solib &so)
> error (_("No namespace found"));
> }
>
> -/* see solib_ops::num_active_namespaces in solist.h. */
> -static int
> -svr4_num_active_namespaces ()
> +int
> +svr4_solib_ops::num_active_namespaces () const
> {
> svr4_info *info = get_svr4_info (current_program_space);
> return info->active_namespaces.size ();
> }
>
> -/* See solib_ops::get_solibs_in_ns in solist.h. */
> -static std::vector<const solib *>
> -svr4_get_solibs_in_ns (int nsid)
> +std::vector<const solib *>
> +svr4_solib_ops::get_solibs_in_ns (int nsid) const
> {
> std::vector<const solib*> ns_solibs;
> svr4_info *info = get_svr4_info (current_program_space);
> @@ -3791,26 +3744,6 @@ svr4_get_solibs_in_ns (int nsid)
> return ns_solibs;
> }
>
> -const struct solib_ops svr4_so_ops =
> -{
> - svr4_relocate_section_addresses,
> - svr4_clear_so,
> - svr4_clear_solib,
> - svr4_solib_create_inferior_hook,
> - svr4_current_sos,
> - open_symbol_file_object,
> - svr4_in_dynsym_resolve_code,
> - solib_bfd_open,
> - svr4_same,
> - svr4_keep_data_in_core,
> - svr4_update_solib_event_breakpoints,
> - svr4_handle_solib_event,
> - svr4_find_solib_addr,
> - svr4_find_solib_ns,
> - svr4_num_active_namespaces,
> - svr4_get_solibs_in_ns,
> -};
> -
> void _initialize_svr4_solib ();
> void
> _initialize_svr4_solib ()
> diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h
> index 1ff9be78a43d..a7be4c902e75 100644
> --- a/gdb/solib-svr4.h
> +++ b/gdb/solib-svr4.h
> @@ -20,12 +20,15 @@
> #ifndef GDB_SOLIB_SVR4_H
> #define GDB_SOLIB_SVR4_H
>
> +#include "gdbarch.h"
> #include "solib.h"
>
> struct objfile;
> -struct solib_ops;
> -
> -extern const solib_ops svr4_so_ops;
> +struct link_map_offsets;
> +struct probe_and_action;
> +struct svr4_info;
> +struct svr4_library_list;
> +struct svr4_so;
>
> /* Link map info to include in an allocated solib entry. */
>
> @@ -50,6 +53,101 @@ struct lm_info_svr4 final : public lm_info
>
> using lm_info_svr4_up = std::unique_ptr<lm_info_svr4>;
>
> +/* What to do when a probe stop occurs. */
> +
> +enum probe_action
> +{
> + /* Something went seriously wrong. Stop using probes and
> + revert to using the older interface. */
> + PROBES_INTERFACE_FAILED,
> +
> + /* No action is required. The shared object list is still
> + valid. */
> + DO_NOTHING,
> +
> + /* The shared object list should be reloaded entirely. */
> + FULL_RELOAD,
> +
> + /* Attempt to incrementally update the shared object list. If
> + the update fails or is not possible, fall back to reloading
> + the list in full. */
> + UPDATE_OR_RELOAD,
> +};
> +
> +/* solib_ops for SVR4 systems. */
> +
> +struct svr4_solib_ops : public solib_ops
> +{
> + void relocate_section_addresses (solib &so, target_section *) const override;
> + void clear_so (const solib &so) const override;
> + void clear_solib (program_space *pspace) override;
> + void create_inferior_hook (int from_tty) override;
> + owning_intrusive_list<solib> current_sos () override;
> + bool open_symbol_file_object (int from_tty) override;
> + bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
> + bool same (const solib &gdb, const solib &inferior) const override;
> + bool keep_data_in_core (CORE_ADDR vaddr, unsigned long size) override;
> + void update_breakpoints () const override;
> + void handle_event () override;
> + std::optional<CORE_ADDR> find_solib_addr (solib &so) const override;
> + bool supports_namespaces () const override { return true; }
> + 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;
> +
> + /* Return the appropriate link map offsets table for the architecture. */
> + virtual link_map_offsets *fetch_link_map_offsets () const = 0;
> +
> + /* This needs to be public because it's accessed from an observer. */
> + void current_sos_direct (svr4_info *info) const;
> +
> +private:
> + void create_probe_breakpoints (svr4_info *info, gdbarch *gdbarch,
> + const std::vector<probe *> *probes,
> + objfile *objfile) const;
> + bool find_and_create_probe_breakpoints (svr4_info *info, gdbarch *gdbarch,
> + obj_section *os,
> + bool with_prefix) const;
> + void create_event_breakpoints (svr4_info *info, gdbarch *gdbarch,
> + CORE_ADDR address) const;
> + int enable_break (svr4_info *info, int from_tty) const;
> + bool is_default_namespace (CORE_ADDR debug_base) const;
> + void free_probes_table (svr4_info *info) const;
> + CORE_ADDR find_r_brk (svr4_info *info) const;
> + CORE_ADDR find_r_ldsomap (svr4_info *info) const;
> + owning_intrusive_list<solib> default_sos (svr4_info *info);
> + int read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
> + std::vector<svr4_so> &sos, int ignore_first) const;
> + lm_info_svr4_up read_lm_info (CORE_ADDR lm_addr) const;
> + int has_lm_dynamic_from_link_map () const;
> + CORE_ADDR lm_addr_check (const solib &so, bfd *abfd) const;
> + CORE_ADDR read_r_next (CORE_ADDR debug_base) const;
> + CORE_ADDR read_r_map (CORE_ADDR debug_base) const;
> + int parse_libraries (const char *document, svr4_library_list *list);
> + int current_sos_via_xfer_libraries (svr4_library_list *list,
> + const char *annex) const;
> + owning_intrusive_list<solib> collect_probes_sos (svr4_info *info);
> + owning_intrusive_list<solib> current_sos_1 (svr4_info *info);
> + owning_intrusive_list<solib> solibs_from_svr4_sos
> + (const std::vector<svr4_so> &sos);
> + void register_event_probe (objfile *objfile, probe *prob, CORE_ADDR address,
> + enum probe_action action) const;
> + void disable_probes_interface (svr4_info *info) const;
> + probe_and_action *event_probe_at (CORE_ADDR address) const;
> + void update_full (svr4_info *info) const;
> + int update_incremental (svr4_info *info, CORE_ADDR debug_base,
> + CORE_ADDR lm) const;
> + bool update_event_breakpoint (breakpoint *b) const;
> + CORE_ADDR find_debug_base (const solib *solib) const;
> +};
> +
> +/* solib_ops for ILP32 SVR4 systems. */
> +
> +struct ilp32_svr4_solib_ops : public svr4_solib_ops
> +{
> + link_map_offsets *fetch_link_map_offsets () const override;
> +};
> +
> /* Critical offsets and sizes which describe struct r_debug and
> struct link_map on SVR4-like targets. All offsets and sizes are
> in bytes unless otherwise specified. */
> @@ -91,26 +189,22 @@ struct link_map_offsets
> int l_name_offset;
> };
>
> -/* set_solib_svr4_fetch_link_map_offsets() is intended to be called by
> - a <arch>_gdbarch_init() function. It is used to establish an
> - architecture specific link_map_offsets fetcher for the architecture
> - being defined. */
> +/* Set the gdbarch methods for SVR4 systems. */
>
> -extern void set_solib_svr4_fetch_link_map_offsets
> - (struct gdbarch *gdbarch, struct link_map_offsets *(*func) (void));
> +extern void set_solib_svr4_ops (gdbarch *gdbarch,
> + gdbarch_new_solib_ops_ftype new_solib_ops);
>
> /* This function is called by thread_db.c. Return the address of the
> link map for the given objfile. */
> extern CORE_ADDR svr4_fetch_objfile_link_map (struct objfile *objfile);
>
> -/* Fetch (and possibly build) an appropriate `struct link_map_offsets'
> - for ILP32 and LP64 SVR4 systems. */
> -extern struct link_map_offsets *svr4_ilp32_fetch_link_map_offsets (void);
> -extern struct link_map_offsets *svr4_lp64_fetch_link_map_offsets (void);
> +/* Return a new solib_ops for ILP32 SVR4 systems. */
>
> -/* Return true if PC lies in the dynamic symbol resolution code of the
> - SVR4 run time loader. */
> -bool svr4_in_dynsym_resolve_code (CORE_ADDR pc);
> +extern solib_ops_up new_svr4_ilp32_solib_ops ();
> +
> +/* Return a new solib_ops for LP64 SVR4 systems. */
> +
> +extern solib_ops_up new_svr4_lp64_solib_ops ();
>
> /* For the MUSL C library, given link map address LM_ADDR, return the
> corresponding TLS module id, or 0 if not found. */
> diff --git a/gdb/solib-target.c b/gdb/solib-target.c
> index 61b841928ff8..5b26f5be34a8 100644
> --- a/gdb/solib-target.c
> +++ b/gdb/solib-target.c
> @@ -209,6 +209,14 @@ static const struct gdb_xml_element library_list_elements[] = {
> { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
> };
>
> +/* See solib-target.h. */
> +
> +solib_ops_up
> +new_target_solib_ops ()
> +{
> + return std::make_unique<target_solib_ops> ();
> +}
> +
> static std::vector<lm_info_target_up>
> solib_target_parse_libraries (const char *library)
> {
> @@ -226,8 +234,8 @@ solib_target_parse_libraries (const char *library)
> }
> #endif
>
> -static owning_intrusive_list<solib>
> -solib_target_current_sos (void)
> +owning_intrusive_list<solib>
> +target_solib_ops::current_sos ()
> {
> owning_intrusive_list<solib> sos;
>
> @@ -245,7 +253,7 @@ solib_target_current_sos (void)
> /* Build a struct solib for each entry on the list. */
> for (lm_info_target_up &info : library_list)
> {
> - auto &new_solib = sos.emplace_back (solib_target_so_ops);
> + auto &new_solib = sos.emplace_back (*this);
>
> /* We don't need a copy of the name in INFO anymore. */
> new_solib.name = std::move (info->name);
> @@ -256,8 +264,9 @@ solib_target_current_sos (void)
> return sos;
> }
>
> -static void
> -solib_target_relocate_section_addresses (solib &so, target_section *sec)
> +void
> +target_solib_ops::relocate_section_addresses (solib &so,
> + target_section *sec) const
> {
> CORE_ADDR offset;
> auto *li = gdb::checked_static_cast<lm_info_target *> (so.lm_info.get ());
> @@ -376,28 +385,11 @@ Could not relocate shared library \"%s\": bad offsets"), so.name.c_str ());
> sec->endaddr += offset;
> }
>
> -static bool
> -solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
> +bool
> +target_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const
> {
> /* We don't have a range of addresses for the dynamic linker; there
> may not be one in the program's address space. So only report
> PLT entries (which may be import stubs). */
> return in_plt_section (pc);
> }
> -
> -const solib_ops solib_target_so_ops =
> -{
> - solib_target_relocate_section_addresses,
> - nullptr,
> - nullptr,
> - nullptr,
> - solib_target_current_sos,
> - nullptr,
> - solib_target_in_dynsym_resolve_code,
> - solib_bfd_open,
> - nullptr,
> - nullptr,
> - nullptr,
> - nullptr,
> - default_find_solib_addr,
> -};
> diff --git a/gdb/solib-target.h b/gdb/solib-target.h
> index f8a22fd6f6ad..8a5f8432345b 100644
> --- a/gdb/solib-target.h
> +++ b/gdb/solib-target.h
> @@ -20,7 +20,19 @@
> #ifndef GDB_SOLIB_TARGET_H
> #define GDB_SOLIB_TARGET_H
>
> -struct solib_ops;
> -extern const solib_ops solib_target_so_ops;
> +#include "solib.h"
> +
> +/* solib_ops for systems fetching solibs from the target. */
> +
> +struct target_solib_ops : solib_ops
> +{
> + void relocate_section_addresses (solib &so, target_section *) const override;
> + owning_intrusive_list<solib> current_sos () override;
> + bool in_dynsym_resolve_code (CORE_ADDR pc) const override;
> +};
> +
> +/* Return a new solib_ops for systems fetching solibs from the target. */
> +
> +solib_ops_up new_target_solib_ops ();
>
> #endif /* GDB_SOLIB_TARGET_H */
> diff --git a/gdb/solib.c b/gdb/solib.c
> index dceab2b865bf..c0e5f803882a 100644
> --- a/gdb/solib.c
> +++ b/gdb/solib.c
> @@ -467,6 +467,12 @@ solib_bfd_open (const char *pathname)
> return abfd;
> }
>
> +gdb_bfd_ref_ptr
> +solib_ops::bfd_open (const char *pathname)
> +{
> + return solib_bfd_open (pathname);
> +}
> +
> /* 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
> @@ -598,8 +604,7 @@ solib::clear ()
> this->name = this->original_name;
>
> /* Do the same for target-specific data. */
> - if (this->ops ().clear_so != NULL)
> - this->ops ().clear_so (*this);
> + this->ops ().clear_so (*this);
> }
>
> lm_info::~lm_info () = default;
> @@ -707,7 +712,7 @@ notify_solib_unloaded (program_space *pspace, const solib &so,
> void
> update_solib_list (int from_tty)
> {
> - const solib_ops *ops = current_program_space->solib_ops ();
> + solib_ops *ops = current_program_space->solib_ops ();
>
> if (ops == nullptr)
> return;
> @@ -722,8 +727,7 @@ update_solib_list (int from_tty)
> have not opened a symbol file, we may be able to get its
> symbols now! */
> if (inf->attach_flag
> - && current_program_space->symfile_object_file == nullptr
> - && ops->open_symbol_file_object != nullptr)
> + && current_program_space->symfile_object_file == nullptr)
> {
> try
> {
> @@ -772,19 +776,8 @@ update_solib_list (int from_tty)
> /* Check to see whether the shared object *gdb also appears in
> the inferior's current list. */
> for (; inferior_iter != inferior.end (); ++inferior_iter)
> - {
> - if (ops->same)
> - {
> - if (ops->same (*gdb_iter, *inferior_iter))
> - break;
> - }
> - else
> - {
> - if (!filename_cmp (gdb_iter->original_name.c_str (),
> - inferior_iter->original_name.c_str ()))
> - break;
> - }
> - }
> + if (ops->same (*gdb_iter, *inferior_iter))
> + break;
>
> /* If the shared object appears on the inferior's list too, then
> it's still loaded, so we don't need to do anything. Delete
> @@ -1032,8 +1025,8 @@ print_solib_list_table (std::vector<const solib *> solib_list,
> first PRINT_NAMESPACE has to be true, second the solib_ops has to
> support multiple namespaces, and third there must be more than one
> active namespace. Fold all these into the PRINT_NAMESPACE condition. */
> - print_namespace = print_namespace && ops->num_active_namespaces != nullptr
> - && ops->num_active_namespaces () > 1;
> + print_namespace = (print_namespace && ops->supports_namespaces ()
> + && ops->num_active_namespaces () > 1);
>
> int num_cols = 4;
> if (print_namespace)
> @@ -1162,7 +1155,7 @@ info_linker_namespace_command (const char *pattern, int from_tty)
>
> /* This command only really makes sense for inferiors that support
> linker namespaces, so we can leave early. */
> - if (ops->num_active_namespaces == nullptr)
> + if (!ops->supports_namespaces ())
> error (_("Current inferior does not support linker namespaces." \
> "Use \"info sharedlibrary\" instead"));
>
> @@ -1272,17 +1265,21 @@ solib_name_from_address (struct program_space *pspace, CORE_ADDR address)
> return nullptr;
> }
>
> +bool
> +solib_ops::same (const solib &a, const solib &b) const
> +{
> + return (filename_cmp (a.original_name.c_str (), b.original_name.c_str ())
> + == 0);
> +}
> +
> /* See solib.h. */
>
> bool
> solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
> {
> - const solib_ops *ops = current_program_space->solib_ops ();
> + solib_ops *ops = current_program_space->solib_ops ();
>
> - if (ops != nullptr && ops->keep_data_in_core != nullptr)
> - return ops->keep_data_in_core (vaddr, size) != 0;
> - else
> - return false;
> + return ops != nullptr && ops->keep_data_in_core (vaddr, size);
> }
>
> /* See solib.h. */
> @@ -1301,9 +1298,8 @@ clear_solib (program_space *pspace)
>
> pspace->solibs ().clear ();
>
> - const solib_ops *ops = pspace->solib_ops ();
> -
> - if (ops != nullptr && ops->clear_solib != nullptr)
> + if (solib_ops *ops = pspace->solib_ops ();
> + ops != nullptr)
> ops->clear_solib (pspace);
> }
>
> @@ -1315,10 +1311,9 @@ clear_solib (program_space *pspace)
> void
> solib_create_inferior_hook (int from_tty)
> {
> - const solib_ops *ops = current_program_space->solib_ops ();
> -
> - if (ops != nullptr && ops->solib_create_inferior_hook != nullptr)
> - ops->solib_create_inferior_hook (from_tty);
> + if (solib_ops *ops = current_program_space->solib_ops ();
> + ops != nullptr)
> + ops->create_inferior_hook (from_tty);
> }
>
> /* See solib.h. */
> @@ -1328,8 +1323,7 @@ in_solib_dynsym_resolve_code (CORE_ADDR pc)
> {
> const solib_ops *ops = current_program_space->solib_ops ();
>
> - return (ops != nullptr && ops->in_dynsym_resolve_code != nullptr
> - && ops->in_dynsym_resolve_code (pc));
> + return ops != nullptr && ops->in_dynsym_resolve_code (pc);
> }
>
> /* Implements the "sharedlibrary" command. */
> @@ -1373,7 +1367,7 @@ update_solib_breakpoints (void)
> {
> const solib_ops *ops = current_program_space->solib_ops ();
>
> - if (ops != nullptr && ops->update_breakpoints != nullptr)
> + if (ops != nullptr)
> ops->update_breakpoints ();
> }
>
> @@ -1382,9 +1376,8 @@ update_solib_breakpoints (void)
> void
> handle_solib_event (void)
> {
> - const solib_ops *ops = current_program_space->solib_ops ();
> -
> - if (ops != nullptr && ops->handle_event != nullptr)
> + if (solib_ops *ops = current_program_space->solib_ops ();
> + ops != nullptr)
> ops->handle_event ();
>
> current_inferior ()->pspace->clear_solib_cache ();
> @@ -1417,7 +1410,8 @@ reload_shared_libraries_1 (int from_tty)
>
> gdb::unique_xmalloc_ptr<char> filename (
> tilde_expand (so.original_name.c_str ()));
> - gdb_bfd_ref_ptr abfd (solib_bfd_open (filename.get ()));
> +
> + gdb_bfd_ref_ptr abfd = so.ops ().bfd_open (filename.get ());
> if (abfd != NULL)
> found_pathname = bfd_get_filename (abfd.get ());
>
> @@ -1479,11 +1473,10 @@ reload_shared_libraries (const char *ignored, int from_tty,
> about ld.so. */
> if (target_has_execution ())
> {
> - const solib_ops *ops = current_program_space->solib_ops ();
> -
> /* Reset or free private data structures not associated with
> solib entries. */
> - if (ops != nullptr && ops->clear_solib != nullptr)
> + if (solib_ops *ops = current_program_space->solib_ops ();
> + ops != nullptr)
> ops->clear_solib (current_program_space);
>
> /* Remove any previous solib event breakpoint. This is usually
> @@ -1810,15 +1803,8 @@ remove_user_added_objfile (struct objfile *objfile)
> }
> }
>
> -/* See solist.h. */
> -
> -std::optional<CORE_ADDR>
> -default_find_solib_addr (solib &so)
> -{
> - return {};
> -}
> -
> /* Implementation of the linker_namespace convenience variable.
> +
> This returns the GDB internal identifier of the linker namespace,
> for the selected frame, as an integer. If the inferior doesn't support
> linker namespaces, this always returns 0. */
> @@ -1833,7 +1819,7 @@ linker_namespace_make_value (gdbarch *gdbarch, internalvar *var,
> for (const solib &so : current_program_space->solibs ())
> if (solib_contains_address_p (so, curr_pc))
> {
> - if (so.ops ().find_solib_ns != nullptr)
> + if (so.ops ().supports_namespaces ())
> nsid = so.ops ().find_solib_ns (so);
>
> break;
> diff --git a/gdb/solib.h b/gdb/solib.h
> index 09d56c08b953..a3104e47e40e 100644
> --- a/gdb/solib.h
> +++ b/gdb/solib.h
> @@ -61,10 +61,10 @@ struct solib : intrusive_list_node<solib>
> /* Constructor
>
> OPS is the solib_ops implementation providing this solib. */
> - explicit solib (const solib_ops &ops) : m_ops (&ops) {}
> + explicit solib (solib_ops &ops) : m_ops (&ops) {}
>
> /* Return the solib_ops implementation providing this solib. */
> - const solib_ops &ops () const
> + solib_ops &ops () const
> { return *m_ops; }
>
> /* Free symbol-file related contents of SO and reset for possible reloading
> @@ -125,7 +125,7 @@ struct solib : intrusive_list_node<solib>
>
> private:
> /* The solib_ops responsible for this solib. */
> - const solib_ops *m_ops;
> + solib_ops *m_ops;
> };
>
> /* A unique pointer to an solib. */
> @@ -133,22 +133,31 @@ using solib_up = std::unique_ptr<solib>;
>
> struct solib_ops
> {
> + virtual ~solib_ops () = default;
> +
> /* Adjust the section binding addresses by the base address at
> which the object was actually mapped. */
> - void (*relocate_section_addresses) (solib &so, target_section *);
> + virtual void relocate_section_addresses (solib &so, target_section *) const
> + = 0;
>
> /* Reset private data structures associated with SO.
> This is called when SO is about to be reloaded.
> - It is also called when SO is about to be freed. */
> - void (*clear_so) (const solib &so);
> + It is also called when SO is about to be freed.
> +
> + Defaults to no-op. */
> + virtual void clear_so (const solib &so) const {}
>
> /* Free private data structures associated to PSPACE. This method
> should not free resources associated to individual solib entries,
> - those are cleared by the clear_so method. */
> - void (*clear_solib) (program_space *pspace);
> + those are cleared by the clear_so method.
>
> - /* Target dependent code to run after child process fork. */
> - void (*solib_create_inferior_hook) (int from_tty);
> + Defaults to no-op. */
> + virtual void clear_solib (program_space *pspace) {}
> +
> + /* Target dependent code to run after child process fork.
> +
> + Defaults to no-op. */
> + virtual void create_inferior_hook (int from_tty) {};
>
> /* Construct a list of the currently loaded shared objects. This
> list does not include an entry for the main executable file.
> @@ -157,45 +166,51 @@ struct solib_ops
> inferior --- we don't examine any of the shared library files
> themselves. The declaration of `struct solib' says which fields
> we provide values for. */
> - owning_intrusive_list<solib> (*current_sos) ();
> + virtual owning_intrusive_list<solib> current_sos () = 0;
>
> /* Find, open, and read the symbols for the main executable. If
> - FROM_TTY is non-zero, allow messages to be printed. */
> - int (*open_symbol_file_object) (int from_ttyp);
> + FROM_TTY is non-zero, allow messages to be printed.
> +
> + Return true if this was done successfully. Defaults to false. */
> + virtual bool open_symbol_file_object (int from_tty) { return false; }
>
> /* Determine if PC lies in the dynamic symbol resolution code of
> - the run time loader. */
> - bool (*in_dynsym_resolve_code) (CORE_ADDR pc);
> + the run time loader.
> +
> + Defaults to false. */
> + virtual bool in_dynsym_resolve_code (CORE_ADDR pc) const
> + { return false; };
>
> /* Find and open shared library binary file. */
> - gdb_bfd_ref_ptr (*bfd_open) (const char *pathname);
> + virtual gdb_bfd_ref_ptr bfd_open (const char *pathname);
>
> - /* Given two solib objects, one from the GDB thread list
> - and another from the list returned by current_sos, return 1
> - if they represent the same library.
> - Falls back to using strcmp on ORIGINAL_NAME when set to nullptr. */
> - int (*same) (const solib &gdb, const solib &inferior);
> + /* Given two solib objects, GDB from the GDB thread list and INFERIOR from the
> + list returned by current_sos, return true if they represent the same library.
> +
> + Defaults to comparing the solib original names using filename_cmp. */
> + virtual bool same (const solib &gdb, const solib &inferior) const;
>
> /* Return whether a region of memory must be kept in a core file
> for shared libraries loaded before "gcore" is used to be
> handled correctly when the core file is loaded. This only
> applies when the section would otherwise not be kept in the
> - core file (in particular, for readonly sections). */
> - int (*keep_data_in_core) (CORE_ADDR vaddr,
> - unsigned long size);
> + core file (in particular, for readonly sections).
>
> - /* Enable or disable optional solib event breakpoints as
> - appropriate. This should be called whenever
> - stop_on_solib_events is changed. This pointer can be
> - NULL, in which case no enabling or disabling is necessary
> - for this target. */
> - void (*update_breakpoints) (void);
> + Defaults to false. */
> + virtual bool keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
> + { return false; };
>
> - /* Target-specific processing of solib events that will be
> - performed before solib_add is called. This pointer can be
> - NULL, in which case no specific preprocessing is necessary
> - for this target. */
> - void (*handle_event) (void);
> + /* Enable or disable optional solib event breakpoints as appropriate. This
> + should be called whenever stop_on_solib_events is changed.
> +
> + Defaults to no-op. */
> + virtual void update_breakpoints () const {};
> +
> + /* Target-specific processing of solib events that will be performed before
> + solib_add is called.
> +
> + Defaults to no-op. */
> + virtual void handle_event () {};
>
> /* Return an address within the inferior's address space which is known
> to be part of SO. If there is no such address, or GDB doesn't know
> @@ -210,28 +225,45 @@ struct solib_ops
> mapped file, and thus to a build-id. GDB can then use this
> information to help locate the shared library objfile, if the objfile
> is not in the expected place (as defined by the shared libraries file
> - name). */
> - std::optional<CORE_ADDR> (*find_solib_addr) (solib &so);
> + name).
>
> - /* Return which linker namespace contains the current so.
> - If the linker or libc does not support linkage namespaces at all
> - (which is basically all of them but solib-svr4), this function should
> - be set to nullptr, so that "info shared" won't add an unnecessary
> - column.
> + The default implementation of returns an empty option, indicating GDB is
> + unable to find an address within the library SO. */
> + virtual std::optional<CORE_ADDR> find_solib_addr (solib &so) const
> + { return {}; };
>
> - If the namespace can not be determined (such as when we're stepping
> - though the dynamic linker), this function should throw a
> - gdb_exception_error. */
> - int (*find_solib_ns) (const solib &so);
> + /* Return true if the linker or libc supports linkage namespaces.
>
> - /* Returns the number of active namespaces in the inferior. */
> - int (*num_active_namespaces) ();
> + Defaults to false. */
> + virtual bool supports_namespaces () const { return false; }
> +
> + /* Return which linker namespace contains SO.
> +
> + The supports_namespaces method must return true for this to be
> + called.
> +
> + Throw an error if the namespace can not be determined (such as when we're
> + stepping though the dynamic linker). */
> + virtual int find_solib_ns (const solib &so) const
> + { gdb_assert_not_reached ("namespaces not supported"); }
> +
> + /* Returns the number of active namespaces in the inferior.
> +
> + The supports_namespaces method must return true for this to be called. */
> + virtual int num_active_namespaces () const
> + { gdb_assert_not_reached ("namespaces not supported"); }
>
> /* Returns all solibs for a given namespace. If the namespace is not
> - active, returns an empty vector. */
> - std::vector<const solib *> (*get_solibs_in_ns) (int ns);
> + active, returns an empty vector.
> +
> + The supports_namespaces method must return true for this to be called. */
> + virtual std::vector<const solib *> get_solibs_in_ns (int ns) const
> + { gdb_assert_not_reached ("namespaces not supported"); }
> };
>
> +/* A unique pointer to an solib_ops. */
> +using solib_ops_up = std::unique_ptr<solib_ops>;
> +
> /* Find main executable binary file. */
> extern gdb::unique_xmalloc_ptr<char> exec_file_find (const char *in_pathname,
> int *fd);
> @@ -246,11 +278,6 @@ extern gdb_bfd_ref_ptr solib_bfd_fopen (const char *pathname, int fd);
> /* Find solib binary file and open it. */
> extern gdb_bfd_ref_ptr solib_bfd_open (const char *in_pathname);
>
> -/* A default implementation of the solib_ops::find_solib_addr callback.
> - This just returns an empty std::optional<CORE_ADDR> indicating GDB is
> - unable to find an address within the library SO. */
> -extern std::optional<CORE_ADDR> default_find_solib_addr (solib &so);
> -
> /* Called when we free all symtabs of PSPACE, to free the shared library
> information as well. */
>
> diff --git a/gdb/sparc-linux-tdep.c b/gdb/sparc-linux-tdep.c
> index 27706b72c7ef..06f6e06ecc9b 100644
> --- a/gdb/sparc-linux-tdep.c
> +++ b/gdb/sparc-linux-tdep.c
> @@ -33,6 +33,7 @@
> #include "tramp-frame.h"
> #include "xml-syscall.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
>
> /* The syscall's XML filename for sparc 32-bit. */
> #define XML_SYSCALL_FILENAME_SPARC32 "syscalls/sparc-linux.xml"
> @@ -436,8 +437,7 @@ sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* GNU/Linux has SVR4-style shared libraries... */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> /* ...which means that we need some special handling when doing
> prologue analysis. */
> diff --git a/gdb/sparc-netbsd-tdep.c b/gdb/sparc-netbsd-tdep.c
> index 84e3a979c6cd..1e9305440d76 100644
> --- a/gdb/sparc-netbsd-tdep.c
> +++ b/gdb/sparc-netbsd-tdep.c
> @@ -313,8 +313,7 @@ sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> frame_unwind_append_unwinder (gdbarch, &sparc32nbsd_sigcontext_frame_unwind);
>
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
> }
>
> void _initialize_sparcnbsd_tdep ();
> diff --git a/gdb/sparc-sol2-tdep.c b/gdb/sparc-sol2-tdep.c
> index 5c6085acabbf..51d93910630c 100644
> --- a/gdb/sparc-sol2-tdep.c
> +++ b/gdb/sparc-sol2-tdep.c
> @@ -207,8 +207,7 @@ sparc32_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* Solaris has SVR4-style shared libraries... */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
>
> /* ...which means that we need some special handling when doing
> prologue analysis. */
> diff --git a/gdb/sparc64-fbsd-tdep.c b/gdb/sparc64-fbsd-tdep.c
> index 738c3d11c59c..9adbcce01b77 100644
> --- a/gdb/sparc64-fbsd-tdep.c
> +++ b/gdb/sparc64-fbsd-tdep.c
> @@ -238,8 +238,7 @@ sparc64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* FreeBSD/sparc64 has SVR4-style shared libraries. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
> }
>
> void _initialize_sparc64fbsd_tdep ();
> diff --git a/gdb/sparc64-linux-tdep.c b/gdb/sparc64-linux-tdep.c
> index 6e7281c91882..af15175b0795 100644
> --- a/gdb/sparc64-linux-tdep.c
> +++ b/gdb/sparc64-linux-tdep.c
> @@ -32,6 +32,7 @@
> #include "tramp-frame.h"
> #include "xml-syscall.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
>
> /* ADI specific si_code */
> #ifndef SEGV_ACCADI
> @@ -383,8 +384,7 @@ sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* GNU/Linux has SVR4-style shared libraries... */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_lp64_svr4_solib_ops);
>
> /* ...which means that we need some special handling when doing
> prologue analysis. */
> diff --git a/gdb/sparc64-netbsd-tdep.c b/gdb/sparc64-netbsd-tdep.c
> index 19195987451c..8b3e013be562 100644
> --- a/gdb/sparc64-netbsd-tdep.c
> +++ b/gdb/sparc64-netbsd-tdep.c
> @@ -266,8 +266,7 @@ sparc64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* NetBSD/sparc64 has SVR4-style shared libraries. */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
> }
>
> void _initialize_sparc64nbsd_tdep ();
> diff --git a/gdb/sparc64-obsd-tdep.c b/gdb/sparc64-obsd-tdep.c
> index 657f548537e7..cd8f3288995b 100644
> --- a/gdb/sparc64-obsd-tdep.c
> +++ b/gdb/sparc64-obsd-tdep.c
> @@ -440,8 +440,7 @@ sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> obsd_init_abi (info, gdbarch);
>
> /* OpenBSD/sparc64 has SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
> set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
>
> /* OpenBSD provides a user-level threads implementation. */
> diff --git a/gdb/sparc64-sol2-tdep.c b/gdb/sparc64-sol2-tdep.c
> index 72a07ecef8ce..bb906efd29b4 100644
> --- a/gdb/sparc64-sol2-tdep.c
> +++ b/gdb/sparc64-sol2-tdep.c
> @@ -214,8 +214,7 @@ sparc64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* Solaris has SVR4-style shared libraries... */
> set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_lp64_solib_ops);
>
> /* ...which means that we need some special handling when doing
> prologue analysis. */
> diff --git a/gdb/tic6x-linux-tdep.c b/gdb/tic6x-linux-tdep.c
> index 280d46dc487b..4dfb6f280bb7 100644
> --- a/gdb/tic6x-linux-tdep.c
> +++ b/gdb/tic6x-linux-tdep.c
> @@ -169,7 +169,7 @@ tic6x_uclinux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> linux_init_abi (info, gdbarch, 0);
>
> /* Shared library handling. */
> - set_gdbarch_so_ops (gdbarch, &dsbt_so_ops);
> + set_gdbarch_new_solib_ops (gdbarch, new_dsbt_solib_ops);
>
> tdep->syscall_next_pc = tic6x_linux_syscall_next_pc;
>
> diff --git a/gdb/tilegx-linux-tdep.c b/gdb/tilegx-linux-tdep.c
> index a0e69543f88b..92e5d0418b12 100644
> --- a/gdb/tilegx-linux-tdep.c
> +++ b/gdb/tilegx-linux-tdep.c
> @@ -19,6 +19,7 @@
>
> #include "osabi.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "glibc-tdep.h"
> #include "solib-svr4.h"
> #include "symtab.h"
> @@ -119,11 +120,9 @@ tilegx_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> /* GNU/Linux uses SVR4-style shared libraries. */
> if (arch_size == 32)
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
> else
> - set_solib_svr4_fetch_link_map_offsets (gdbarch,
> - linux_lp64_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_lp64_svr4_solib_ops);
>
> /* Enable TLS support. */
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> diff --git a/gdb/vax-netbsd-tdep.c b/gdb/vax-netbsd-tdep.c
> index 34a9150fdb27..fabd98218d4b 100644
> --- a/gdb/vax-netbsd-tdep.c
> +++ b/gdb/vax-netbsd-tdep.c
> @@ -32,8 +32,7 @@ vaxnbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> nbsd_init_abi (info, gdbarch);
>
> /* NetBSD ELF uses SVR4-style shared libraries. */
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
> }
>
> void _initialize_vaxnbsd_tdep ();
> diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
> index d8858a7f1450..75437a145d6a 100644
> --- a/gdb/windows-tdep.c
> +++ b/gdb/windows-tdep.c
> @@ -862,10 +862,25 @@ windows_get_siginfo_type (struct gdbarch *gdbarch)
> return siginfo_type;
> }
>
> +/* solib_ops for Windows systems. */
> +
> +struct windows_solib_ops : target_solib_ops
> +{
> + void create_inferior_hook (int from_tty) override;
> +};
> +
> +/* Return a new solib_ops for Windows systems. */
> +
> +static solib_ops_up
> +new_windows_solib_ops ()
> +{
> + return std::make_unique<windows_solib_ops> ();
> +}
> +
> /* Implement the "solib_create_inferior_hook" solib_ops method. */
>
> -static void
> -windows_solib_create_inferior_hook (int from_tty)
> +void
> +windows_solib_ops::create_inferior_hook (int from_tty)
> {
> CORE_ADDR exec_base = 0;
>
> @@ -910,8 +925,6 @@ windows_solib_create_inferior_hook (int from_tty)
> }
> }
>
> -static solib_ops windows_so_ops;
> -
> /* Common parts for gdbarch initialization for the Windows and Cygwin OS
> ABIs. */
>
> @@ -928,10 +941,7 @@ windows_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch)
> set_gdbarch_iterate_over_objfiles_in_search_order
> (gdbarch, windows_iterate_over_objfiles_in_search_order);
>
> - windows_so_ops = solib_target_so_ops;
> - windows_so_ops.solib_create_inferior_hook
> - = windows_solib_create_inferior_hook;
> - set_gdbarch_so_ops (gdbarch, &windows_so_ops);
> + set_gdbarch_new_solib_ops (gdbarch, new_windows_solib_ops);
>
> set_gdbarch_get_siginfo_type (gdbarch, windows_get_siginfo_type);
> }
> diff --git a/gdb/xtensa-linux-tdep.c b/gdb/xtensa-linux-tdep.c
> index b72d683b3b40..eaa46cf788ab 100644
> --- a/gdb/xtensa-linux-tdep.c
> +++ b/gdb/xtensa-linux-tdep.c
> @@ -20,6 +20,7 @@
> #include "xtensa-tdep.h"
> #include "osabi.h"
> #include "linux-tdep.h"
> +#include "solib-svr4-linux.h"
> #include "solib-svr4.h"
> #include "symtab.h"
> #include "gdbarch.h"
> @@ -111,8 +112,7 @@ xtensa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>
> linux_init_abi (info, gdbarch, 0);
>
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, linux_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_linux_ilp32_svr4_solib_ops);
>
> set_gdbarch_gdb_signal_from_target (gdbarch,
> xtensa_linux_gdb_signal_from_target);
> diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
> index a4bbffb8f114..85a6bee5b6f5 100644
> --- a/gdb/xtensa-tdep.c
> +++ b/gdb/xtensa-tdep.c
> @@ -3238,8 +3238,7 @@ xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> set_gdbarch_iterate_over_regset_sections
> (gdbarch, xtensa_iterate_over_regset_sections);
>
> - set_solib_svr4_fetch_link_map_offsets
> - (gdbarch, svr4_ilp32_fetch_link_map_offsets);
> + set_solib_svr4_ops (gdbarch, new_svr4_ilp32_solib_ops);
>
> /* Hook in the ABI-specific overrides, if they have been registered. */
> gdbarch_init_osabi (info, gdbarch);
next prev parent reply other threads:[~2025-06-12 12:57 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-09 19:40 [PATCH v2 1/4] gdb/solib: add solib -> solib_ops backlink Simon Marchi
2025-06-09 19:40 ` [PATCH v2 2/4] gdb/solib: use solib::ops for operations that concern a single solib Simon Marchi
2025-06-09 19:40 ` [PATCH v2 3/4] gdb/progspace: add solib_ops pointer in program_space Simon Marchi
2025-06-11 18:14 ` Guinevere Larsen
2025-06-11 18:43 ` Simon Marchi
2025-06-16 18:41 ` Simon Marchi
2025-06-16 18:53 ` Simon Marchi
2025-06-16 19:38 ` Guinevere Larsen
2025-06-16 19:41 ` Simon Marchi
2025-06-09 19:40 ` [PATCH v2 4/4] gdb/solib: C++ify solib_ops Simon Marchi
2025-06-12 12:56 ` Guinevere Larsen [this message]
2025-06-12 15:02 ` Simon Marchi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=fa840ac6-b0c1-41f4-ba87-9d0b5b326aac@redhat.com \
--to=guinevere@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=simon.marchi@efficios.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox