]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: Allow replayed threads to read and write pseudo registers
authorGuinevere Larsen <guinevere@redhat.com>
Wed, 19 Jun 2024 20:16:33 +0000 (17:16 -0300)
committerGuinevere Larsen <guinevere@redhat.com>
Mon, 28 Oct 2024 13:46:33 +0000 (10:46 -0300)
In an effort to support AVX instructions when recording, we need to
allow replaying threads to access pseudo registers. Currently, if
we try to do that gdb will fail in a call to validate_registers_access,
because the thread is executing so GDB thinks it is unsafe to read
pseudo registers.

When replaying, the thread is really executing for all intents and
purposes, but the execution is just having GDB change values on
registers, so it will always be safe to read and write pseudo registers.
This commit changes functions that check for register access to allow
access when we are replaying. The check to whether we are replaying must
not happen when writing a core file, as record_full_list could be nullptr,
so we only check it if the thread is executing.

As of this commit, I don't know of a way to trigger this commit without
AVX support on record, so a test isn't provided. However, as soon as
record-full supports saving ymm registers, the AVX tests will test this
as well.

Approved-By: Tom Tromey <tom@tromey.com>
gdb/record-full.c
gdb/record-full.h
gdb/thread.c

index a681ef9fe51d5cf682ea14f107dee42ce156e30b..074d0cd63fc1e25274a6d5129677ee9253af1612 100644 (file)
@@ -370,6 +370,15 @@ record_full_is_used (void)
          || t == &record_full_core_ops);
 }
 
+/* see record-full.h.  */
+bool
+record_full_is_replaying ()
+{
+  auto target = dynamic_cast<record_full_target *>
+                 (current_inferior ()->target_at (record_stratum));
+  return target != nullptr && RECORD_FULL_IS_REPLAY;
+}
+
 
 /* Command lists for "set/show record full".  */
 static struct cmd_list_element *set_record_full_cmdlist;
index e8eb041311bf1abe869979f1540683fed0bb5566..07f97d241a21b0f7b1bfff260717108df4e58b38 100644 (file)
@@ -31,6 +31,9 @@ extern int record_full_arch_list_add_end (void);
 /* Returns true if the process record target is open.  */
 extern int record_full_is_used (void);
 
+/* Whether the inferior is being replayed, or is executing normally.  */
+extern bool record_full_is_replaying ();
+
 extern scoped_restore_tmpl<int> record_full_gdb_operation_disable_set ();
 
 #endif /* RECORD_FULL_H */
index 4ee469368610ebc0dbb7a057e549d256720100fe..5892b158603a7d11cb7c7efc3346f01714797201 100644 (file)
@@ -50,6 +50,7 @@
 #include "inline-frame.h"
 #include "stack.h"
 #include "interps.h"
+#include "record-full.h"
 
 /* See gdbthread.h.  */
 
@@ -998,7 +999,13 @@ validate_registers_access (void)
      reason, but is marked running from the user's perspective.  E.g.,
      the thread is waiting for its turn in the step-over queue.  */
   if (tp->executing ())
-    error (_("Selected thread is running."));
+    {
+      /* If we are replaying with the record-full subsystem, even though
+        the thread is executing, it is always safe to read from it since
+        replay execution is just GDB reading and writing to a regcache.  */
+      if (!record_full_is_replaying ())
+       error (_("Selected thread is running."));
+    }
 }
 
 /* See gdbthread.h.  */
@@ -1016,7 +1023,11 @@ can_access_registers_thread (thread_info *thread)
 
   /* ... or from a spinning thread.  FIXME: see validate_registers_access.  */
   if (thread->executing ())
-    return false;
+    {
+      /* See validate_registers_access.  */
+      if (!record_full_is_replaying ())
+       return false;
+    }
 
   return true;
 }