[RFC,1/7] gdb: add replay diversion interface to target_ops

Message ID dwr&m2&5go-xsf2xytnhuiq.mz36_p7l7jvxs0cu5cwevxzpl3c-@mail.bob131.so
State New
Headers show
Series
  • gdb: replay diversion support
Related show

Commit Message

Luis Machado via Gdb-patches June 1, 2021, 7:10 p.m.
Some process replay targets do not support arbitrary manipulations of
their state, but instead require that things like memory or register
writes be done within a temporary 'replay diversion'. This commit adds
an interface through which such targets can announce their support of
such diversions and through which GDB can control the target's replay
diversion state.

gdb/ChangeLog:

2021-06-01  George Barrett  <bob@bob131.so>

	* target-delegates.c: Regenerate.
	* target.c (target_needs_replay_diversion)
	(target_in_replay_diversion, target_start_replay_diversion)
	(target_end_replay_diversion): Add definitions.
	* target.h (target_ops::needs_replay_diversion)
	(target_ops::in_replay_diversion)
	(target_ops::start_replay_diversion)
	(target_ops::end_replay_diversion): Add declarations.
	(target_needs_replay_diversion, target_in_replay_diversion)
	(target_start_replay_diversion, target_end_replay_diversion):
	Likewise.
---
 gdb/target-delegates.c | 100 +++++++++++++++++++++++++++++++++++++++++
 gdb/target.c           |  32 +++++++++++++
 gdb/target.h           |  31 +++++++++++++
 3 files changed, 163 insertions(+)

-- 
2.31.1

Patch

diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 3e759a2f80e..12ce70193c8 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -160,6 +160,10 @@  struct dummy_target : public target_ops
   bool record_is_replaying (ptid_t arg0) override;
   bool record_will_replay (ptid_t arg0, int arg1) override;
   void record_stop_replaying () override;
+  bool needs_replay_diversion () override;
+  bool in_replay_diversion () override;
+  void start_replay_diversion () override;
+  void end_replay_diversion () override;
   void goto_record_begin () override;
   void goto_record_end () override;
   void goto_record (ULONGEST arg0) override;
@@ -335,6 +339,10 @@  struct debug_target : public target_ops
   bool record_is_replaying (ptid_t arg0) override;
   bool record_will_replay (ptid_t arg0, int arg1) override;
   void record_stop_replaying () override;
+  bool needs_replay_diversion () override;
+  bool in_replay_diversion () override;
+  void start_replay_diversion () override;
+  void end_replay_diversion () override;
   void goto_record_begin () override;
   void goto_record_end () override;
   void goto_record (ULONGEST arg0) override;
@@ -4113,6 +4121,98 @@  debug_target::record_stop_replaying ()
   fputs_unfiltered (")\n", gdb_stdlog);
 }
 
+bool
+target_ops::needs_replay_diversion ()
+{
+  return this->beneath ()->needs_replay_diversion ();
+}
+
+bool
+dummy_target::needs_replay_diversion ()
+{
+  return false;
+}
+
+bool
+debug_target::needs_replay_diversion ()
+{
+  bool result;
+  fprintf_unfiltered (gdb_stdlog, "-> %s->needs_replay_diversion (...)\n", this->beneath ()->shortname ());
+  result = this->beneath ()->needs_replay_diversion ();
+  fprintf_unfiltered (gdb_stdlog, "<- %s->needs_replay_diversion (", this->beneath ()->shortname ());
+  fputs_unfiltered (") = ", gdb_stdlog);
+  target_debug_print_bool (result);
+  fputs_unfiltered ("\n", gdb_stdlog);
+  return result;
+}
+
+bool
+target_ops::in_replay_diversion ()
+{
+  return this->beneath ()->in_replay_diversion ();
+}
+
+bool
+dummy_target::in_replay_diversion ()
+{
+  return false;
+}
+
+bool
+debug_target::in_replay_diversion ()
+{
+  bool result;
+  fprintf_unfiltered (gdb_stdlog, "-> %s->in_replay_diversion (...)\n", this->beneath ()->shortname ());
+  result = this->beneath ()->in_replay_diversion ();
+  fprintf_unfiltered (gdb_stdlog, "<- %s->in_replay_diversion (", this->beneath ()->shortname ());
+  fputs_unfiltered (") = ", gdb_stdlog);
+  target_debug_print_bool (result);
+  fputs_unfiltered ("\n", gdb_stdlog);
+  return result;
+}
+
+void
+target_ops::start_replay_diversion ()
+{
+  this->beneath ()->start_replay_diversion ();
+}
+
+void
+dummy_target::start_replay_diversion ()
+{
+  tcomplain ();
+}
+
+void
+debug_target::start_replay_diversion ()
+{
+  fprintf_unfiltered (gdb_stdlog, "-> %s->start_replay_diversion (...)\n", this->beneath ()->shortname ());
+  this->beneath ()->start_replay_diversion ();
+  fprintf_unfiltered (gdb_stdlog, "<- %s->start_replay_diversion (", this->beneath ()->shortname ());
+  fputs_unfiltered (")\n", gdb_stdlog);
+}
+
+void
+target_ops::end_replay_diversion ()
+{
+  this->beneath ()->end_replay_diversion ();
+}
+
+void
+dummy_target::end_replay_diversion ()
+{
+  tcomplain ();
+}
+
+void
+debug_target::end_replay_diversion ()
+{
+  fprintf_unfiltered (gdb_stdlog, "-> %s->end_replay_diversion (...)\n", this->beneath ()->shortname ());
+  this->beneath ()->end_replay_diversion ();
+  fprintf_unfiltered (gdb_stdlog, "<- %s->end_replay_diversion (", this->beneath ()->shortname ());
+  fputs_unfiltered (")\n", gdb_stdlog);
+}
+
 void
 target_ops::goto_record_begin ()
 {
diff --git a/gdb/target.c b/gdb/target.c
index 6babfc56256..7fbc6a1cd8d 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -4134,6 +4134,38 @@  target_record_stop_replaying (void)
 
 /* See target.h.  */
 
+bool
+target_needs_replay_diversion (void)
+{
+  return current_inferior ()->top_target ()->needs_replay_diversion ();
+}
+
+/* See target.h.  */
+
+bool
+target_in_replay_diversion (void)
+{
+  return current_inferior ()->top_target ()->in_replay_diversion ();
+}
+
+/* See target.h.  */
+
+void
+target_start_replay_diversion (void)
+{
+  current_inferior ()->top_target ()->start_replay_diversion ();
+}
+
+/* See target.h.  */
+
+void
+target_end_replay_diversion (void)
+{
+  current_inferior ()->top_target ()->end_replay_diversion ();
+}
+
+/* See target.h.  */
+
 void
 target_goto_record_begin (void)
 {
diff --git a/gdb/target.h b/gdb/target.h
index e22f9038197..4b0ddb40fa8 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1218,6 +1218,25 @@  struct target_ops
     virtual void record_stop_replaying ()
       TARGET_DEFAULT_IGNORE ();
 
+    /* Return TRUE if THIS is a deterministic replay target that
+       requires a special environment (a 'replay diversion') to be set
+       up before memory or register writes are possible.  */
+    virtual bool needs_replay_diversion ()
+      TARGET_DEFAULT_RETURN (false);
+
+    /* Return TRUE if the target is currently in a replay
+       diversion.  */
+    virtual bool in_replay_diversion ()
+      TARGET_DEFAULT_RETURN (false);
+
+    /* Begin a replay diversion.  */
+    virtual void start_replay_diversion ()
+      TARGET_DEFAULT_NORETURN (tcomplain ());
+
+    /* End the current replay diversion.  */
+    virtual void end_replay_diversion ()
+      TARGET_DEFAULT_NORETURN (tcomplain ());
+
     /* Go to the begin of the execution trace.  */
     virtual void goto_record_begin ()
       TARGET_DEFAULT_NORETURN (tcomplain ());
@@ -2537,6 +2556,18 @@  extern int target_record_will_replay (ptid_t ptid, int dir);
 /* See to_record_stop_replaying in struct target_ops.  */
 extern void target_record_stop_replaying (void);
 
+/* See needs_replay_diversion in struct target_ops.  */
+extern bool target_needs_replay_diversion (void);
+
+/* See in_replay_diversion in struct target_ops.  */
+extern bool target_in_replay_diversion (void);
+
+/* See start_replay_diversion in struct target_ops.  */
+extern void target_start_replay_diversion (void);
+
+/* See end_replay_diversion in struct target_ops.  */
+extern void target_end_replay_diversion (void);
+
 /* See to_goto_record_begin in struct target_ops.  */
 extern void target_goto_record_begin (void);