[04/10] btrace: Handle stepping and goto for auxiliary instructions.

Message ID 1559119673-30516-5-git-send-email-felix.willgerodt@intel.com
State New, archived
Headers

Commit Message

Willgerodt, Felix May 29, 2019, 8:47 a.m. UTC
  From: Felix Willgerodt <felix.willgerodt@intel.com>

Print the auxiliary data when stepping. Don't allow to goto an auxiliary
instruction.

This patch is in preparation for the ptwrite feature, which is based on
auxiliary instructions.

2019-05-29  Felix Willgerodt  <felix.willgerodt@intel.com>

gdb/ChangeLog:
	* record-btrace.c: (record_btrace_single_step_forward): Handle
	BTRACE_INSN_AUX.
	(record_btrace_single_step_backward): Likewise.
	(record_btrace_goto): Likewise.

---
 gdb/record-btrace.c | 52 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 8 deletions(-)
  

Comments

Metzger, Markus T June 4, 2019, 12:35 p.m. UTC | #1
Hello Felix,

> @@ -2378,13 +2380,26 @@ record_btrace_single_step_forward (struct thread_info
> *tp)
>    if (record_btrace_replay_at_breakpoint (tp))
>      return btrace_step_stopped ();
> 
> -  /* Skip gaps during replay.  If we end up at a gap (at the end of the trace),
> -     jump back to the instruction at which we started.  */
>    start = *replay;

Please preserve the order of comment and code.

> +
> +  /* Skip gaps during replay.  If we end up at a gap (at the end of the trace),
> +     jump back to the instruction at which we started.  If we're stepping a
> +     BTRACE_INSN_AUX instruction, print the ptwrite string and skip the

Should this say 'print the aux data'?

> +     instruction.  */
>    do
>      {
>        unsigned int steps;
> 
> +      /* If we're stepping a BTRACE_INSN_AUX instruction, print the auxiliary
> +	 data and skip the instruction.  If we are at the end of the trace, jump
> +	 back to the instruction at which we started.  */
> +      bfun = &replay->btinfo->functions[replay->call_index];
> +      next_insn = bfun->insn[replay->insn_index + 1];

The below btrace_insn_next () already advances REPLAY to the next instruction.  You may
use btrace_insn_next (replay) to get that instruction.

> +
> +      if (next_insn.iclass == BTRACE_INSN_AUX)
> +	printf_unfiltered (
> +	    "[%s]\n", btinfo->aux_data[next_insn.aux_data_index].c_str ());
> +
>        /* We will bail out here if we continue stepping after reaching the end
>  	 of the execution history.  */
>        steps = btrace_insn_next (replay, 1);
> @@ -2394,7 +2409,8 @@ record_btrace_single_step_forward (struct thread_info
> *tp)
>  	  return btrace_step_no_history ();
>  	}
>      }
> -  while (btrace_insn_get (replay) == NULL);
> +  while (btrace_insn_get (replay) == NULL
> +	 || next_insn.iclass == BTRACE_INSN_AUX);

Since we now call btrace_insn_get (replay) inside the loop, we should rewrite this.

> @@ -2452,6 +2470,22 @@ record_btrace_single_step_backward (struct
> thread_info *tp)
>    if (record_btrace_replay_at_breakpoint (tp))
>      return btrace_step_stopped ();
> 
> +  /* Check if we're stepping a BTRACE_INSN_AUX instruction and skip it.  */
> +  bfun = &replay->btinfo->functions[replay->call_index];
> +  prev_insn = bfun->insn[replay->insn_index];

Same here.

> +
> +  if (prev_insn.iclass == BTRACE_INSN_AUX)
> +    {
> +      printf_unfiltered ("[%s]\n",
> +			 btinfo->aux_data[prev_insn.aux_data_index].c_str ());
> +      unsigned int steps = btrace_insn_prev (replay, 1);
> +      if (steps == 0)
> +	{
> +	  *replay = start;
> +	  return btrace_step_no_history ();
> +	}
> +    }
> +
>    return btrace_step_spurious ();
>  }
> 
> @@ -2853,25 +2887,27 @@ record_btrace_target::goto_record_end ()
>  /* The goto_record method of target record-btrace.  */
> 
>  void
> -record_btrace_target::goto_record (ULONGEST insn)
> +record_btrace_target::goto_record (ULONGEST insn_number)
>  {
>    struct thread_info *tp;
>    struct btrace_insn_iterator it;
>    unsigned int number;
>    int found;
> 
> -  number = insn;
> +  number = insn_number;
> 
>    /* Check for wrap-arounds.  */
> -  if (number != insn)
> +  if (number != insn_number)
>      error (_("Instruction number out of range."));
> 
>    tp = require_btrace_thread ();
> 
>    found = btrace_find_insn_by_number (&it, &tp->btrace, number);
> +  const struct btrace_insn *insn = btrace_insn_get (&it);

You need to check FOUND before dereferencing IT.

> 
> -  /* Check if the instruction could not be found or is a gap.  */
> -  if (found == 0 || btrace_insn_get (&it) == NULL)
> +  /* Check if the instruction could not be found or is a gap or an
> +     auxilliary instruction.  */
> +  if ((found == 0) || (insn == NULL) || (insn->iclass == BTRACE_INSN_AUX))
>      error (_("No such instruction."));
> 
>    record_btrace_set_replay (tp, &it);
> --
> 2.20.1

Thanks,
Markus.
Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Gary Kershaw
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
  

Patch

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 5f70c4838a9..573326924a2 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -2366,6 +2366,8 @@  record_btrace_single_step_forward (struct thread_info *tp)
 {
   struct btrace_insn_iterator *replay, end, start;
   struct btrace_thread_info *btinfo;
+  const struct btrace_function *bfun;
+  struct btrace_insn next_insn;
 
   btinfo = &tp->btrace;
   replay = btinfo->replay;
@@ -2378,13 +2380,26 @@  record_btrace_single_step_forward (struct thread_info *tp)
   if (record_btrace_replay_at_breakpoint (tp))
     return btrace_step_stopped ();
 
-  /* Skip gaps during replay.  If we end up at a gap (at the end of the trace),
-     jump back to the instruction at which we started.  */
   start = *replay;
+
+  /* Skip gaps during replay.  If we end up at a gap (at the end of the trace),
+     jump back to the instruction at which we started.  If we're stepping a
+     BTRACE_INSN_AUX instruction, print the ptwrite string and skip the
+     instruction.  */
   do
     {
       unsigned int steps;
 
+      /* If we're stepping a BTRACE_INSN_AUX instruction, print the auxiliary
+	 data and skip the instruction.  If we are at the end of the trace, jump
+	 back to the instruction at which we started.  */
+      bfun = &replay->btinfo->functions[replay->call_index];
+      next_insn = bfun->insn[replay->insn_index + 1];
+
+      if (next_insn.iclass == BTRACE_INSN_AUX)
+	printf_unfiltered (
+	    "[%s]\n", btinfo->aux_data[next_insn.aux_data_index].c_str ());
+
       /* We will bail out here if we continue stepping after reaching the end
 	 of the execution history.  */
       steps = btrace_insn_next (replay, 1);
@@ -2394,7 +2409,8 @@  record_btrace_single_step_forward (struct thread_info *tp)
 	  return btrace_step_no_history ();
 	}
     }
-  while (btrace_insn_get (replay) == NULL);
+  while (btrace_insn_get (replay) == NULL
+	 || next_insn.iclass == BTRACE_INSN_AUX);
 
   /* Determine the end of the instruction trace.  */
   btrace_insn_end (&end, btinfo);
@@ -2415,6 +2431,8 @@  record_btrace_single_step_backward (struct thread_info *tp)
 {
   struct btrace_insn_iterator *replay, start;
   struct btrace_thread_info *btinfo;
+  const struct btrace_function *bfun;
+  struct btrace_insn prev_insn;
 
   btinfo = &tp->btrace;
   replay = btinfo->replay;
@@ -2452,6 +2470,22 @@  record_btrace_single_step_backward (struct thread_info *tp)
   if (record_btrace_replay_at_breakpoint (tp))
     return btrace_step_stopped ();
 
+  /* Check if we're stepping a BTRACE_INSN_AUX instruction and skip it.  */
+  bfun = &replay->btinfo->functions[replay->call_index];
+  prev_insn = bfun->insn[replay->insn_index];
+
+  if (prev_insn.iclass == BTRACE_INSN_AUX)
+    {
+      printf_unfiltered ("[%s]\n",
+			 btinfo->aux_data[prev_insn.aux_data_index].c_str ());
+      unsigned int steps = btrace_insn_prev (replay, 1);
+      if (steps == 0)
+	{
+	  *replay = start;
+	  return btrace_step_no_history ();
+	}
+    }
+
   return btrace_step_spurious ();
 }
 
@@ -2853,25 +2887,27 @@  record_btrace_target::goto_record_end ()
 /* The goto_record method of target record-btrace.  */
 
 void
-record_btrace_target::goto_record (ULONGEST insn)
+record_btrace_target::goto_record (ULONGEST insn_number)
 {
   struct thread_info *tp;
   struct btrace_insn_iterator it;
   unsigned int number;
   int found;
 
-  number = insn;
+  number = insn_number;
 
   /* Check for wrap-arounds.  */
-  if (number != insn)
+  if (number != insn_number)
     error (_("Instruction number out of range."));
 
   tp = require_btrace_thread ();
 
   found = btrace_find_insn_by_number (&it, &tp->btrace, number);
+  const struct btrace_insn *insn = btrace_insn_get (&it);
 
-  /* Check if the instruction could not be found or is a gap.  */
-  if (found == 0 || btrace_insn_get (&it) == NULL)
+  /* Check if the instruction could not be found or is a gap or an
+     auxilliary instruction.  */
+  if ((found == 0) || (insn == NULL) || (insn->iclass == BTRACE_INSN_AUX))
     error (_("No such instruction."));
 
   record_btrace_set_replay (tp, &it);