[RFC,4/7] gdb/inferior: add replay diversion state

Message ID 5yfn9g53kiwn&wiicyy26&et06cmyl3eqy_43xui2x6pt071-/t9@mail.bob131.so
State New
Headers show
Series
  • gdb: replay diversion support
Related show

Commit Message

Tom de Vries via Gdb-patches June 1, 2021, 7:10 p.m.
Adds API to `struct inferior' for managing replay diversions of the
underlying target.

gdb/ChangeLog:

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

	* inferior.c (inferior::want_replay_diversion)
	(inferior::finish_replay_diversion): Add definitions.
	* inferior.h (inferior::want_replay_diversion)
	(inferior::finish_replay_diversion): Add declarations.
	(inferior::wants_replay_diversion_p)
	(inferior::m_wants_replay_diversion): Add definitions.
	* infrun.c (clear_proceed_status): Make sure to end any
	lingering replay diversion before proceeding.
---
 gdb/inferior.c | 23 +++++++++++++++++++++++
 gdb/inferior.h | 21 +++++++++++++++++++++
 gdb/infrun.c   |  6 ++++++
 3 files changed, 50 insertions(+)

-- 
2.31.1

Comments

Tom de Vries via Gdb-patches June 22, 2021, 9:50 p.m. | #1
On Wed, Jun 02, 2021 at 05:10:52AM +1000, George Barrett via Gdb-patches wrote:
> Adds API to `struct inferior' for managing replay diversions of the

> underlying target.

> 

> gdb/ChangeLog:

> 

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

> 

> 	* inferior.c (inferior::want_replay_diversion)

> 	(inferior::finish_replay_diversion): Add definitions.

> 	* inferior.h (inferior::want_replay_diversion)

> 	(inferior::finish_replay_diversion): Add declarations.

> 	(inferior::wants_replay_diversion_p)

> 	(inferior::m_wants_replay_diversion): Add definitions.

> 	* infrun.c (clear_proceed_status): Make sure to end any

> 	lingering replay diversion before proceeding.

> ---

>  gdb/inferior.c | 23 +++++++++++++++++++++++

>  gdb/inferior.h | 21 +++++++++++++++++++++

>  gdb/infrun.c   |  6 ++++++

>  3 files changed, 50 insertions(+)

> 

> diff --git a/gdb/inferior.c b/gdb/inferior.c

> index 059839ec962..4c8de42cf6d 100644

> --- a/gdb/inferior.c

> +++ b/gdb/inferior.c

> @@ -121,6 +121,29 @@ inferior::do_all_continuations ()

>      }

>  }

>  

> +scoped_want_replay_diversion

> +inferior::want_replay_diversion ()

> +{

> +  if (!process_target ()->needs_replay_diversion ())

> +    return {};

> +  if (!process_target ()->in_replay_diversion ())

> +    {

> +      process_target ()->start_replay_diversion ();

> +      printf_unfiltered ("[New replay diversion]\n");


Hi,

I am wondering if this message should be translatable, i.e. using

      printf_unfiltered (_("[New replay diversion]\n"));

instead.

> +    }

> +  return make_scoped_restore (&m_wants_replay_diversion, true);

> +}

> +

> +void

> +inferior::finish_replay_diversion ()

> +{

> +  if (process_target ()->in_replay_diversion () && !m_wants_replay_diversion)

> +    {

> +      process_target ()->end_replay_diversion ();

> +      printf_unfiltered ("[Replay diversion ended]\n");


Same here, could probably use _().

Best,
Lancelot.

> +    }

> +}

> +

>  struct inferior *

>  add_inferior_silent (int pid)

>  {

> diff --git a/gdb/inferior.h b/gdb/inferior.h

> index f4b8b025e35..9cc939a60af 100644

> --- a/gdb/inferior.h

> +++ b/gdb/inferior.h

> @@ -317,6 +317,9 @@ extern void set_current_inferior (inferior *);

>     selected.  */

>  extern void switch_to_inferior_no_thread (inferior *inf);

>  

> +using scoped_want_replay_diversion

> +  = gdb::optional<scoped_restore_tmpl<bool>>;

> +

>  /* GDB represents the state of each program execution with an object

>     called an inferior.  An inferior typically corresponds to a process

>     but is more general and applies also to targets that do not have a

> @@ -438,6 +441,21 @@ class inferior : public refcounted_object

>    void set_tty (const char *terminal_name);

>    const char *tty ();

>  

> +  /* Begin a replay diversion (if the target supports it and if not

> +     already started) and prevent finish_replay_diversion() from

> +     having any effect for the lifetime of the returned scoped

> +     restore.  */

> +  scoped_want_replay_diversion want_replay_diversion ();

> +

> +  /* Return TRUE if some code still wants a replay diversion to

> +     persist.  */

> +  inline bool wants_replay_diversion_p () { return m_wants_replay_diversion; }

> +

> +  /* If the target is currently in a replay diversion and no scoped

> +     restores from want_replay_diversion() are still alive, end the

> +     diversion.  */

> +  void finish_replay_diversion ();

> +

>    /* Convenient handle (GDB inferior id).  Unique across all

>       inferiors.  */

>    int num = 0;

> @@ -566,6 +584,9 @@ class inferior : public refcounted_object

>  

>    /* The list of continuations.  */

>    std::list<std::function<void ()>> m_continuations;

> +

> +  /* TRUE if calls to finish_replay_diversion() should be ignored.  */

> +  bool m_wants_replay_diversion = false;

>  };

>  

>  /* Keep a registry of per-inferior data-pointers required by other GDB

> diff --git a/gdb/infrun.c b/gdb/infrun.c

> index 166f1e513c4..58ed3e92161 100644

> --- a/gdb/infrun.c

> +++ b/gdb/infrun.c

> @@ -2677,6 +2677,12 @@ clear_proceed_status (int step)

>  				     execution_direction))

>      target_record_stop_replaying ();

>  

> +  /* If we're preparing to proceed and no-one needs the replay

> +     diversion anymore, end it.  It doesn't make sense to continue

> +     replay within a diversion session.  */

> +  if (inferior_ptid != null_ptid)

> +    current_inferior ()->finish_replay_diversion ();

> +

>    if (!non_stop && inferior_ptid != null_ptid)

>      {

>        ptid_t resume_ptid = user_visible_resume_ptid (step);

> -- 

> 2.31.1

Patch

diff --git a/gdb/inferior.c b/gdb/inferior.c
index 059839ec962..4c8de42cf6d 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -121,6 +121,29 @@  inferior::do_all_continuations ()
     }
 }
 
+scoped_want_replay_diversion
+inferior::want_replay_diversion ()
+{
+  if (!process_target ()->needs_replay_diversion ())
+    return {};
+  if (!process_target ()->in_replay_diversion ())
+    {
+      process_target ()->start_replay_diversion ();
+      printf_unfiltered ("[New replay diversion]\n");
+    }
+  return make_scoped_restore (&m_wants_replay_diversion, true);
+}
+
+void
+inferior::finish_replay_diversion ()
+{
+  if (process_target ()->in_replay_diversion () && !m_wants_replay_diversion)
+    {
+      process_target ()->end_replay_diversion ();
+      printf_unfiltered ("[Replay diversion ended]\n");
+    }
+}
+
 struct inferior *
 add_inferior_silent (int pid)
 {
diff --git a/gdb/inferior.h b/gdb/inferior.h
index f4b8b025e35..9cc939a60af 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -317,6 +317,9 @@  extern void set_current_inferior (inferior *);
    selected.  */
 extern void switch_to_inferior_no_thread (inferior *inf);
 
+using scoped_want_replay_diversion
+  = gdb::optional<scoped_restore_tmpl<bool>>;
+
 /* GDB represents the state of each program execution with an object
    called an inferior.  An inferior typically corresponds to a process
    but is more general and applies also to targets that do not have a
@@ -438,6 +441,21 @@  class inferior : public refcounted_object
   void set_tty (const char *terminal_name);
   const char *tty ();
 
+  /* Begin a replay diversion (if the target supports it and if not
+     already started) and prevent finish_replay_diversion() from
+     having any effect for the lifetime of the returned scoped
+     restore.  */
+  scoped_want_replay_diversion want_replay_diversion ();
+
+  /* Return TRUE if some code still wants a replay diversion to
+     persist.  */
+  inline bool wants_replay_diversion_p () { return m_wants_replay_diversion; }
+
+  /* If the target is currently in a replay diversion and no scoped
+     restores from want_replay_diversion() are still alive, end the
+     diversion.  */
+  void finish_replay_diversion ();
+
   /* Convenient handle (GDB inferior id).  Unique across all
      inferiors.  */
   int num = 0;
@@ -566,6 +584,9 @@  class inferior : public refcounted_object
 
   /* The list of continuations.  */
   std::list<std::function<void ()>> m_continuations;
+
+  /* TRUE if calls to finish_replay_diversion() should be ignored.  */
+  bool m_wants_replay_diversion = false;
 };
 
 /* Keep a registry of per-inferior data-pointers required by other GDB
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 166f1e513c4..58ed3e92161 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2677,6 +2677,12 @@  clear_proceed_status (int step)
 				     execution_direction))
     target_record_stop_replaying ();
 
+  /* If we're preparing to proceed and no-one needs the replay
+     diversion anymore, end it.  It doesn't make sense to continue
+     replay within a diversion session.  */
+  if (inferior_ptid != null_ptid)
+    current_inferior ()->finish_replay_diversion ();
+
   if (!non_stop && inferior_ptid != null_ptid)
     {
       ptid_t resume_ptid = user_visible_resume_ptid (step);