[06/26] gdbserver: turn part of get_thread_regcache into regcache::fetch
Commit Message
Extract out a piece of code in get_thread_regcache that fetches the
registers from the target, and turn it into a method of 'regcache'.
---
gdbserver/regcache.cc | 23 +++++++++++++++--------
gdbserver/regcache.h | 3 +++
2 files changed, 18 insertions(+), 8 deletions(-)
Comments
On 2/28/23 06:28, Tankut Baris Aktemur via Gdb-patches wrote:
> Extract out a piece of code in get_thread_regcache that fetches the
> registers from the target, and turn it into a method of 'regcache'.
> ---
> gdbserver/regcache.cc | 23 +++++++++++++++--------
> gdbserver/regcache.h | 3 +++
> 2 files changed, 18 insertions(+), 8 deletions(-)
>
> diff --git a/gdbserver/regcache.cc b/gdbserver/regcache.cc
> index 2a8dc17ed6a..89ecdfec6f3 100644
> --- a/gdbserver/regcache.cc
> +++ b/gdbserver/regcache.cc
> @@ -48,19 +48,26 @@ get_thread_regcache (struct thread_info *thread, bool fetch)
> regcache->thread = thread;
> }
>
> - if (fetch && regcache->registers_valid == 0)
> + if (fetch)
> + regcache->fetch ();
> +
> + return regcache;
> +}
> +
> +void
> +regcache::fetch ()
> +{
> + if (registers_valid == 0)
> {
> scoped_restore_current_thread restore_thread;
> + gdb_assert (this->thread != nullptr);
> + switch_to_thread (this->thread);
>
> - switch_to_thread (thread);
> /* Invalidate all registers, to prevent stale left-overs. */
> - memset (regcache->register_status, REG_UNAVAILABLE,
> - regcache->tdesc->reg_defs.size ());
> - fetch_inferior_registers (regcache, -1);
> - regcache->registers_valid = 1;
> + memset (register_status, REG_UNAVAILABLE, tdesc->reg_defs.size ());
> + fetch_inferior_registers (this, -1);
> + registers_valid = 1;
> }
> -
> - return regcache;
Ok, so this is one of the uses of the regcache::thread field. Given
that, as of today (before your series), a thread knows its regcache, but
a regcache doesn't know its thread (if any), it could be the other way
around. You could have a thread_info::fetch_registers method that does
the above. This way, the regcache stays a relatively dumb box of
register data, oblivious to where the bytes come from. Again, I don't
have yet the full context of the rest of the series.
Another improvement I'd like to see: would it be relatively easy to
change fetch_inferior_registers to pass the thread down, and avoid the
switch_to_thread? I guess you wouldn't need to pass the regcache down
anymore, because the target function would know it needs to put the
register data in thread->regcache. Doing the same in GDB is an enormous
amount of work, but I peeked at the GDBserver code, and it seems
do-able.
Simon
@@ -48,19 +48,26 @@ get_thread_regcache (struct thread_info *thread, bool fetch)
regcache->thread = thread;
}
- if (fetch && regcache->registers_valid == 0)
+ if (fetch)
+ regcache->fetch ();
+
+ return regcache;
+}
+
+void
+regcache::fetch ()
+{
+ if (registers_valid == 0)
{
scoped_restore_current_thread restore_thread;
+ gdb_assert (this->thread != nullptr);
+ switch_to_thread (this->thread);
- switch_to_thread (thread);
/* Invalidate all registers, to prevent stale left-overs. */
- memset (regcache->register_status, REG_UNAVAILABLE,
- regcache->tdesc->reg_defs.size ());
- fetch_inferior_registers (regcache, -1);
- regcache->registers_valid = 1;
+ memset (register_status, REG_UNAVAILABLE, tdesc->reg_defs.size ());
+ fetch_inferior_registers (this, -1);
+ registers_valid = 1;
}
-
- return regcache;
}
/* See gdbsupport/common-regcache.h. */
@@ -67,6 +67,9 @@ struct regcache : public reg_buffer_common
/* See gdbsupport/common-regcache.h. */
bool raw_compare (int regnum, const void *buf, int offset) const override;
+
+ /* Fetch the registers from the target, if not done already. */
+ void fetch ();
};
void regcache_cpy (struct regcache *dst, struct regcache *src);