From: Guinevere Larsen <guinevere@redhat.com>
To: Simon Marchi <simon.marchi@efficios.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH v2 3/4] gdb/progspace: add solib_ops pointer in program_space
Date: Wed, 11 Jun 2025 15:14:08 -0300 [thread overview]
Message-ID: <f3a6effa-9e35-4698-a13a-de3e49228396@redhat.com> (raw)
In-Reply-To: <20250609194146.137730-3-simon.marchi@efficios.com>
On 6/9/25 4:40 PM, Simon Marchi wrote:
> New in v2: remove commented out code in target.c and spurious change in
> gdb.mi/mi-detach.exp.
>
> The subsequent C++ification patch in this series will allocate one
> instance of solib_ops per program space. That instance will be held in
> struct program_space. As a small step towards this, add an `solib_ops
> *` field to `struct program_space`. This field represents the solib_ops
> currently used to manage the solibs in that program space. Initialize
> it with the result of `gdbarch_so_ops` in `post_create_inferior`, and
> use it whenever we need to do some solib stuff, rather than using
> `gdbarch_so_ops` directly.
>
> The difficulty here is knowing when exactly to set and unset the solib
> ops. What I have here passes the testsuite on Linux, but with more
> testing we will probably discover more spots where it's needed.
>
> The C++ification patch will turn this field into a unique pointer.
>
> Change-Id: Ide8ddc57328895720fcd645d46dc34491f84c656
> ---
> gdb/corelow.c | 2 +-
> gdb/infcmd.c | 15 ++++++++-------
> gdb/inferior.h | 9 ++++++++-
> gdb/infrun.c | 11 +++++++++--
> gdb/progspace.h | 20 ++++++++++++++++++++
> gdb/solib.c | 44 +++++++++++++++++++++++--------------------
> gdb/target.c | 1 +
> gdb/tracectf.c | 2 +-
> gdb/tracefile-tfile.c | 2 +-
> 9 files changed, 73 insertions(+), 33 deletions(-)
>
> diff --git a/gdb/corelow.c b/gdb/corelow.c
> index b5895de9e9c6..d92585c67bfd 100644
> --- a/gdb/corelow.c
> +++ b/gdb/corelow.c
> @@ -1180,7 +1180,7 @@ core_target_open (const char *arg, int from_tty)
> if (current_program_space->exec_bfd () == nullptr)
> set_gdbarch_from_file (current_program_space->core_bfd ());
>
> - post_create_inferior (from_tty);
> + post_create_inferior (from_tty, true);
>
> /* Now go through the target stack looking for threads since there
> may be a thread_stratum target loaded on top of target core by
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index e9b58ce55210..1adad5c3eaa3 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -224,14 +224,11 @@ strip_bg_char (const char *args, int *bg_char_p)
> return make_unique_xstrdup (args);
> }
>
> -/* Common actions to take after creating any sort of inferior, by any
> - means (running, attaching, connecting, et cetera). The target
> - should be stopped. */
> +/* See inferior.h. */
>
> void
> -post_create_inferior (int from_tty)
> +post_create_inferior (int from_tty, bool set_pspace_solib_ops)
> {
> -
> /* Be sure we own the terminal in case write operations are performed. */
> target_terminal::ours_for_output ();
>
> @@ -261,6 +258,10 @@ post_create_inferior (int from_tty)
> throw;
> }
>
> + if (set_pspace_solib_ops)
> + current_program_space->set_solib_ops
> + (*gdbarch_so_ops (current_inferior ()->arch ()));
> +
> if (current_program_space->exec_bfd ())
> {
> const unsigned solib_add_generation
> @@ -482,7 +483,7 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
>
> /* Pass zero for FROM_TTY, because at this point the "run" command
> has done its thing; now we are setting up the running program. */
> - post_create_inferior (0);
> + post_create_inferior (0, true);
>
> /* Queue a pending event so that the program stops immediately. */
> if (run_how == RUN_STOP_AT_FIRST_INSN)
> @@ -2506,7 +2507,7 @@ setup_inferior (int from_tty)
> /* Take any necessary post-attaching actions for this platform. */
> target_post_attach (inferior_ptid.pid ());
>
> - post_create_inferior (from_tty);
> + post_create_inferior (from_tty, true);
> }
>
> /* What to do after the first program stops after attaching. */
> diff --git a/gdb/inferior.h b/gdb/inferior.h
> index 54f5229b420f..fe94e289bdc7 100644
> --- a/gdb/inferior.h
> +++ b/gdb/inferior.h
> @@ -213,7 +213,14 @@ extern ptid_t gdb_startup_inferior (pid_t pid, int num_traps);
>
> extern void setup_inferior (int from_tty);
>
> -extern void post_create_inferior (int from_tty);
> +/* Common actions to take after creating any sort of inferior, by any
> + means (running, attaching, connecting, et cetera). The target
> + should be stopped.
> +
> + If SET_PSPACE_SOLIB_OPS is true, initialize the program space's solib
> + provider using the current inferior's architecture. */
> +
> +extern void post_create_inferior (int from_tty, bool set_pspace_solib_ops);
>
> extern void attach_command (const char *, int);
>
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 2e02642c52a4..5cdf66d26dcb 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -472,6 +472,7 @@ holding the child stopped. Try \"set %ps\" or \"%ps\".\n"),
>
> inferior *parent_inf = current_inferior ();
> inferior *child_inf = nullptr;
> + bool child_has_new_pspace = false;
>
> gdb_assert (parent_inf->thread_waiting_for_vfork_done == nullptr);
>
> @@ -536,6 +537,7 @@ holding the child stopped. Try \"set %ps\" or \"%ps\".\n"),
> else
> {
> child_inf->pspace = new program_space (new_address_space ());
> + child_has_new_pspace = true;
> child_inf->aspace = child_inf->pspace->aspace;
> child_inf->removable = true;
> clone_program_space (child_inf->pspace, parent_inf->pspace);
> @@ -625,6 +627,7 @@ holding the child stopped. Try \"set %ps\" or \"%ps\".\n"),
> else
> {
> child_inf->pspace = new program_space (new_address_space ());
> + child_has_new_pspace = true;
> child_inf->aspace = child_inf->pspace->aspace;
> child_inf->removable = true;
> child_inf->symfile_flags = SYMFILE_NO_READ;
> @@ -723,7 +726,8 @@ holding the child stopped. Try \"set %ps\" or \"%ps\".\n"),
> maybe_restore.emplace ();
>
> switch_to_thread (*child_inf->threads ().begin ());
> - post_create_inferior (0);
> +
> + post_create_inferior (0, child_has_new_pspace);
> }
>
> return false;
> @@ -1321,6 +1325,7 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
> we don't want those to be satisfied by the libraries of the
> previous incarnation of this process. */
> no_shared_libraries (current_program_space);
> + current_program_space->unset_solib_ops ();
>
> inferior *execing_inferior = current_inferior ();
> inferior *following_inferior;
> @@ -1377,6 +1382,8 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
> registers. */
> target_find_description ();
>
> + current_program_space->set_solib_ops
> + (*gdbarch_so_ops (following_inferior->arch ()));
> gdb::observers::inferior_execd.notify (execing_inferior, following_inferior);
>
> breakpoint_re_set ();
> @@ -3818,7 +3825,7 @@ start_remote (int from_tty)
> /* Now that the inferior has stopped, do any bookkeeping like
> loading shared libraries. We want to do this before normal_stop,
> so that the displayed frame is up to date. */
> - post_create_inferior (from_tty);
> + post_create_inferior (from_tty, true);
>
> normal_stop ();
> }
> diff --git a/gdb/progspace.h b/gdb/progspace.h
> index 5e5d5edd9b4b..abb448195d74 100644
> --- a/gdb/progspace.h
> +++ b/gdb/progspace.h
> @@ -231,6 +231,23 @@ struct program_space
> is outside all objfiles in this progspace. */
> struct objfile *objfile_for_address (CORE_ADDR address);
>
> + /* 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)
> + {
> + gdb_assert (m_solib_ops == nullptr);
> + m_solib_ops = &ops;
> + };
> +
> + /* Unset this program space's solib provider. */
> + void unset_solib_ops ()
> + { m_solib_ops = nullptr; }
> +
> + /* Get this program space's solib provider. */
> + const struct solib_ops *solib_ops () const
> + { return m_solib_ops; }
> +
> /* Return the list of all the solibs in this program space. */
> owning_intrusive_list<solib> &solibs ()
> { return m_solib_list; }
> @@ -355,6 +372,9 @@ struct program_space
> /* All known objfiles are kept in a linked list. */
> 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;
> +
> /* List of shared objects mapped into this space. Managed by
> solib.c. */
> owning_intrusive_list<solib> m_solib_list;
> diff --git a/gdb/solib.c b/gdb/solib.c
> index de3469da6e91..dceab2b865bf 100644
> --- a/gdb/solib.c
> +++ b/gdb/solib.c
> @@ -707,7 +707,10 @@ notify_solib_unloaded (program_space *pspace, const solib &so,
> void
> update_solib_list (int from_tty)
> {
> - const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
> + const solib_ops *ops = current_program_space->solib_ops ();
> +
> + if (ops == nullptr)
> + return;
>
> /* We can reach here due to changing solib-search-path or the
> sysroot, before having any inferior. */
> @@ -1021,7 +1024,7 @@ print_solib_list_table (std::vector<const solib *> solib_list,
> gdbarch *gdbarch = current_inferior ()->arch ();
> /* "0x", a little whitespace, and two hex digits per byte of pointers. */
> int addr_width = 4 + (gdbarch_ptr_bit (gdbarch) / 4);
> - const solib_ops *ops = gdbarch_so_ops (gdbarch);
> + const solib_ops *ops = current_program_space->solib_ops ();
> struct ui_out *uiout = current_uiout;
> bool so_missing_debug_info = false;
>
> @@ -1155,7 +1158,8 @@ info_sharedlibrary_command (const char *pattern, int from_tty)
> static void
> info_linker_namespace_command (const char *pattern, int from_tty)
> {
> - const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
> + const solib_ops *ops = current_program_space->solib_ops ();
> +
> /* This command only really makes sense for inferiors that support
> linker namespaces, so we can leave early. */
> if (ops->num_active_namespaces == nullptr)
> @@ -1273,9 +1277,9 @@ solib_name_from_address (struct program_space *pspace, CORE_ADDR address)
> bool
> solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
> {
> - const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
> + const solib_ops *ops = current_program_space->solib_ops ();
>
> - if (ops->keep_data_in_core)
> + if (ops != nullptr && ops->keep_data_in_core != nullptr)
Can this function be called before the program space is fully setup?
Otherwise I think we should either assume that it was set correctly, or
assert it. Better to be loud and easy to find the bug than accidentally
adding a regression in a hard-to-spot place.
This goes to all other similar places where you check for ops != nullptr.
--
Cheers,
Guinevere Larsen
She/Her/Hers
> return ops->keep_data_in_core (vaddr, size) != 0;
> else
> return false;
> @@ -1286,8 +1290,6 @@ solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
> void
> clear_solib (program_space *pspace)
> {
> - const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
> -
> for (solib &so : pspace->solibs ())
> {
> bool still_in_use
> @@ -1299,7 +1301,9 @@ clear_solib (program_space *pspace)
>
> pspace->solibs ().clear ();
>
> - if (ops->clear_solib != nullptr)
> + const solib_ops *ops = pspace->solib_ops ();
> +
> + if (ops != nullptr && ops->clear_solib != nullptr)
> ops->clear_solib (pspace);
> }
>
> @@ -1311,9 +1315,9 @@ clear_solib (program_space *pspace)
> void
> solib_create_inferior_hook (int from_tty)
> {
> - const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
> + const solib_ops *ops = current_program_space->solib_ops ();
>
> - if (ops->solib_create_inferior_hook != nullptr)
> + if (ops != nullptr && ops->solib_create_inferior_hook != nullptr)
> ops->solib_create_inferior_hook (from_tty);
> }
>
> @@ -1322,10 +1326,10 @@ solib_create_inferior_hook (int from_tty)
> bool
> in_solib_dynsym_resolve_code (CORE_ADDR pc)
> {
> - const auto in_dynsym_resolve_code
> - = gdbarch_so_ops (current_inferior ()->arch ())->in_dynsym_resolve_code;
> + const solib_ops *ops = current_program_space->solib_ops ();
>
> - return in_dynsym_resolve_code && in_dynsym_resolve_code (pc);
> + return (ops != nullptr && ops->in_dynsym_resolve_code != nullptr
> + && ops->in_dynsym_resolve_code (pc));
> }
>
> /* Implements the "sharedlibrary" command. */
> @@ -1367,9 +1371,9 @@ no_shared_libraries_command (const char *ignored, int from_tty)
> void
> update_solib_breakpoints (void)
> {
> - const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
> + const solib_ops *ops = current_program_space->solib_ops ();
>
> - if (ops->update_breakpoints != NULL)
> + if (ops != nullptr && ops->update_breakpoints != nullptr)
> ops->update_breakpoints ();
> }
>
> @@ -1378,9 +1382,9 @@ update_solib_breakpoints (void)
> void
> handle_solib_event (void)
> {
> - const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
> + const solib_ops *ops = current_program_space->solib_ops ();
>
> - if (ops->handle_event != NULL)
> + if (ops != nullptr && ops->handle_event != nullptr)
> ops->handle_event ();
>
> current_inferior ()->pspace->clear_solib_cache ();
> @@ -1464,8 +1468,6 @@ reload_shared_libraries (const char *ignored, int from_tty,
> {
> reload_shared_libraries_1 (from_tty);
>
> - const solib_ops *ops = gdbarch_so_ops (current_inferior ()->arch ());
> -
> /* Creating inferior hooks here has two purposes. First, if we reload
> shared libraries then the address of solib breakpoint we've computed
> previously might be no longer valid. For example, if we forgot to set
> @@ -1477,9 +1479,11 @@ 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->clear_solib != nullptr)
> + if (ops != nullptr && ops->clear_solib != nullptr)
> ops->clear_solib (current_program_space);
>
> /* Remove any previous solib event breakpoint. This is usually
> diff --git a/gdb/target.c b/gdb/target.c
> index 522bed8e939c..7a296572830e 100644
> --- a/gdb/target.c
> +++ b/gdb/target.c
> @@ -2464,6 +2464,7 @@ target_pre_inferior ()
> if (!gdbarch_has_global_solist (current_inferior ()->arch ()))
> {
> no_shared_libraries (current_program_space);
> + current_program_space->unset_solib_ops ();
>
> invalidate_target_mem_regions ();
>
> diff --git a/gdb/tracectf.c b/gdb/tracectf.c
> index 1650e676d814..ce0b0079a29e 100644
> --- a/gdb/tracectf.c
> +++ b/gdb/tracectf.c
> @@ -1174,7 +1174,7 @@ ctf_target_open (const char *args, int from_tty)
> merge_uploaded_trace_state_variables (&uploaded_tsvs);
> merge_uploaded_tracepoints (&uploaded_tps);
>
> - post_create_inferior (from_tty);
> + post_create_inferior (from_tty, true);
> }
>
> /* This is the implementation of target_ops method to_close. Destroy
> diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c
> index 5f8b338df4cc..093b10e51d6e 100644
> --- a/gdb/tracefile-tfile.c
> +++ b/gdb/tracefile-tfile.c
> @@ -567,7 +567,7 @@ tfile_target_open (const char *arg, int from_tty)
>
> merge_uploaded_tracepoints (&uploaded_tps);
>
> - post_create_inferior (from_tty);
> + post_create_inferior (from_tty, true);
> }
>
> /* Interpret the given line from the definitions part of the trace
next prev parent reply other threads:[~2025-06-11 18:15 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 [this message]
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
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=f3a6effa-9e35-4698-a13a-de3e49228396@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