[06/26] gdbserver: turn part of get_thread_regcache into regcache::fetch

Message ID d2bd6c9812d5565f7ce91501892680ba54ec4522.1677582744.git.tankut.baris.aktemur@intel.com
State New
Headers
Series gdbserver: refactor regcache and allow gradually populating |

Commit Message

Tankut Baris Aktemur Feb. 28, 2023, 11:28 a.m. UTC
  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

Simon Marchi Dec. 21, 2023, 8:48 p.m. UTC | #1
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
  

Patch

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;
 }
 
 /* See gdbsupport/common-regcache.h.  */
diff --git a/gdbserver/regcache.h b/gdbserver/regcache.h
index 053ed08b20f..7eae6cb724a 100644
--- a/gdbserver/regcache.h
+++ b/gdbserver/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);