public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v9 00/10] Extensions for PTWRITE
@ 2023-07-04 12:35 Felix Willgerodt
  2023-07-04 12:35 ` [PATCH v9 01/10] btrace: Introduce auxiliary instructions Felix Willgerodt
                   ` (10 more replies)
  0 siblings, 11 replies; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:35 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Willgerodt, Felix

From: "Willgerodt, Felix" <felix.willgerodt@intel.com>

v8 can be found here:
https://sourceware.org/pipermail/gdb-patches/2023-March/198177.html

I changed the following commits, mainly based on comments from Simon (thanks!):

* Patch 4:
Changed error message for going to an aux instruction.
* Patch 5:
I fixed the possibility of dangling aux objects in python, by erroring out
earlier and some restructuring.
* Patch 8:
I added parsing the config bit from a file provided by Linux, instead of
hardcoding it.
* Patch 9:
This changed a bit. I restructured the ptwrite filtering book-keeping and
registration. Now we use a factory pattern for registration. I also removed
the handler for inferior exit events in favour of one for the newly added
thread_exit event. That simplified the python file.
* Patch 10:
This is now using an optional for the filter function return value and is
printing the payload directly, if we don't have a filter or no Python
support. The documentation changed a lot due to the new way to register filters.

Thanks,
Felix


Felix Willgerodt (10):
  btrace: Introduce auxiliary instructions.
  btrace: Enable auxiliary instructions in record instruction-history.
  btrace: Enable auxiliary instructions in record function-call-history.
  btrace: Handle stepping and goto for auxiliary instructions.
  python: Introduce gdb.RecordAuxiliary class.
  python: Add clear() to gdb.Record.
  btrace, gdbserver: Add ptwrite to btrace_config_pt.
  btrace, linux: Enable ptwrite packets.
  btrace, python: Enable ptwrite filter registration.
  btrace: Extend ptwrite event decoding.

 gdb/NEWS                                      |   7 +
 gdb/btrace.c                                  |  72 ++-
 gdb/btrace.h                                  |  41 +-
 gdb/config.in                                 |   3 +
 gdb/configure                                 |  11 +
 gdb/data-directory/Makefile.in                |   1 +
 gdb/disasm-flags.h                            |   1 +
 gdb/doc/gdb.texinfo                           |  32 +-
 gdb/doc/python.texi                           | 166 ++++++
 gdb/extension-priv.h                          |   5 +
 gdb/extension.c                               |  13 +
 gdb/extension.h                               |   3 +
 gdb/features/btrace-conf.dtd                  |   1 +
 gdb/guile/guile.c                             |   1 +
 gdb/nat/linux-btrace.c                        |  58 ++
 gdb/python/lib/gdb/ptwrite.py                 |  77 +++
 gdb/python/py-record-btrace.c                 | 185 +++++-
 gdb/python/py-record-btrace.h                 |   6 +
 gdb/python/py-record.c                        |  78 ++-
 gdb/python/py-record.h                        |   7 +
 gdb/python/python-internal.h                  |   3 +
 gdb/python/python.c                           |   2 +
 gdb/record-btrace.c                           | 105 +++-
 gdb/record.c                                  |  10 +
 gdb/record.h                                  |   5 +-
 gdb/remote.c                                  |  33 ++
 gdb/testsuite/gdb.btrace/i386-ptwrite.S       | 550 ++++++++++++++++++
 gdb/testsuite/gdb.btrace/ptwrite.c            |  39 ++
 gdb/testsuite/gdb.btrace/ptwrite.exp          | 202 +++++++
 gdb/testsuite/gdb.btrace/x86_64-ptwrite.S     | 544 +++++++++++++++++
 gdb/testsuite/gdb.python/py-record-btrace.exp |   4 +
 gdb/testsuite/lib/gdb.exp                     |  72 +++
 gdbserver/linux-low.cc                        |   3 +
 gdbserver/server.cc                           |  18 +
 gdbsupport/btrace-common.h                    |   6 +
 gdbsupport/common.m4                          |   2 +
 gdbsupport/config.in                          |   3 +
 gdbsupport/configure                          |  11 +
 38 files changed, 2345 insertions(+), 35 deletions(-)
 create mode 100644 gdb/python/lib/gdb/ptwrite.py
 create mode 100644 gdb/testsuite/gdb.btrace/i386-ptwrite.S
 create mode 100644 gdb/testsuite/gdb.btrace/ptwrite.c
 create mode 100644 gdb/testsuite/gdb.btrace/ptwrite.exp
 create mode 100644 gdb/testsuite/gdb.btrace/x86_64-ptwrite.S

-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v9 01/10] btrace: Introduce auxiliary instructions.
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
@ 2023-07-04 12:35 ` Felix Willgerodt
  2023-07-04 12:44   ` Eli Zaretskii
  2023-07-04 12:35 ` [PATCH v9 02/10] btrace: Enable auxiliary instructions in record instruction-history Felix Willgerodt
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:35 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Felix Willgerodt

Auxiliary instructions are pseudo instructions pointing to auxiliary data.
This auxiliary data can be printed in all commands displaying (record
function-call-history, record instruction-history) or stepping through
(stepi etc.) the execution history, which will be introduced in the next
commits.

This patch is in preparation for the new ptwrite feature, which is based on
auxiliary instructions.
---
 gdb/btrace.c        |  2 ++
 gdb/btrace.h        | 24 +++++++++++++++++++++---
 gdb/doc/gdb.texinfo |  3 +++
 3 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/gdb/btrace.c b/gdb/btrace.c
index dbdcea0a8ea..2c20763b570 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -1823,6 +1823,8 @@ btrace_clear_history (struct btrace_thread_info *btinfo)
   btinfo->insn_history = NULL;
   btinfo->call_history = NULL;
   btinfo->replay = NULL;
+
+  btinfo->aux_data.clear ();
 }
 
 /* Clear the branch trace maintenance histories in BTINFO.  */
diff --git a/gdb/btrace.h b/gdb/btrace.h
index 0ec84113217..dd80d3e6806 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -52,7 +52,10 @@ enum btrace_insn_class
   BTRACE_INSN_RETURN,
 
   /* The instruction is an unconditional jump.  */
-  BTRACE_INSN_JUMP
+  BTRACE_INSN_JUMP,
+
+  /* The instruction is a pseudo instruction containing auxiliary data.  */
+  BTRACE_INSN_AUX
 };
 
 /* Instruction flags.  */
@@ -68,8 +71,19 @@ DEF_ENUM_FLAGS_TYPE (enum btrace_insn_flag, btrace_insn_flags);
    This represents a single instruction in a branch trace.  */
 struct btrace_insn
 {
-  /* The address of this instruction.  */
-  CORE_ADDR pc;
+  union
+  {
+    /* The address of this instruction.  Applies to btrace_insn with
+       iclass == BTRACE_INSN_OTHER or
+       iclass == BTRACE_INSN_CALL or
+       iclass == BTRACE_INSN_RETURN or
+       iclass == BTRACE_INSN_JUMP.  */
+    CORE_ADDR pc;
+
+    /* Index into btrace_info::aux_data.  Applies to btrace_insn with
+       iclass == BTRACE_INSN_AUX.  */
+    uint64_t aux_data_index;
+  };
 
   /* The size of this instruction in bytes.  */
   gdb_byte size;
@@ -330,6 +344,10 @@ struct btrace_thread_info
      function segment i will be at index (i - 1).  */
   std::vector<btrace_function> functions;
 
+  /* Optional auxiliary information that is printed in all commands
+     displaying or stepping through the execution history.  */
+  std::vector<std::string> aux_data;
+
   /* The function level offset.  When added to each function's LEVEL,
      this normalizes the function levels such that the smallest level
      becomes zero.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b10c06ae91f..7c7e64f3733 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7660,6 +7660,9 @@ Moxie, PowerPC, PowerPC64, S/390, and x86 (i386/amd64) running
 GNU/Linux.  Process record and replay can be used both when native
 debugging, and when remote debugging via @code{gdbserver}.
 
+When recording an inferior, @value{GDBN} may print auxiliary information
+during stepping commands and commands displaying the execution history.
+
 For architecture environments that support process record and replay,
 @value{GDBN} provides the following commands:
 
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v9 02/10] btrace: Enable auxiliary instructions in record instruction-history.
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
  2023-07-04 12:35 ` [PATCH v9 01/10] btrace: Introduce auxiliary instructions Felix Willgerodt
@ 2023-07-04 12:35 ` Felix Willgerodt
  2023-07-04 12:45   ` Eli Zaretskii
  2023-07-04 12:35 ` [PATCH v9 03/10] btrace: Enable auxiliary instructions in record function-call-history Felix Willgerodt
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:35 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Felix Willgerodt

Print the auxiliary data when a btrace_insn of type BTRACE_INSN_AUX
is encountered in the instruction-history.  Printing is active by default,
it can be silenced with the /a modifier.

This patch is in preparation for the new ptwrite feature, which is based on
auxiliary instructions.
---
 gdb/disasm-flags.h  |  1 +
 gdb/doc/gdb.texinfo |  3 +++
 gdb/record-btrace.c | 14 ++++++++++++++
 gdb/record.c        |  5 +++++
 4 files changed, 23 insertions(+)

diff --git a/gdb/disasm-flags.h b/gdb/disasm-flags.h
index e2e8a7a82e5..08b2d506493 100644
--- a/gdb/disasm-flags.h
+++ b/gdb/disasm-flags.h
@@ -34,6 +34,7 @@ enum gdb_disassembly_flag : unsigned
     DISASSEMBLY_SOURCE = (0x1 << 5),
     DISASSEMBLY_SPECULATIVE = (0x1 << 6),
     DISASSEMBLY_RAW_BYTES = (0x1 << 7),
+    DISASSEMBLY_OMIT_AUX_INSN = (0x1 << 8),
   };
 DEF_ENUM_FLAGS_TYPE (enum gdb_disassembly_flag, gdb_disassembly_flags);
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 7c7e64f3733..5f15875f5dd 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -8078,6 +8078,9 @@ To better align the printed instructions when the trace contains
 instructions from more than one function, the function name may be
 omitted by specifying the @code{/f} modifier.
 
+Printing auxiliary information is enabled by default and can be
+omitted with the @code{/a} modifier.
+
 Speculatively executed instructions are prefixed with @samp{?}.  This
 feature is not available for all recording formats.
 
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 97447d3e8f8..36247d5b31d 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -827,6 +827,20 @@ btrace_insn_history (struct ui_out *uiout,
 	  btrace_ui_out_decode_error (uiout, btrace_insn_get_error (&it),
 				      conf->format);
 	}
+      else if (insn->iclass == BTRACE_INSN_AUX)
+	{
+	  if ((flags & DISASSEMBLY_OMIT_AUX_INSN) != 0)
+	    continue;
+
+	  uiout->field_fmt ("insn-number", "%u", btrace_insn_number (&it));
+	  uiout->text ("\t");
+	  uiout->spaces (3);
+	  uiout->text ("[");
+	  uiout->field_fmt ("aux-data", "%s",
+			    it.btinfo->aux_data.at
+			     (insn->aux_data_index).c_str ());
+	  uiout->text ("]\n");
+	}
       else
 	{
 	  struct disasm_insn dinsn;
diff --git a/gdb/record.c b/gdb/record.c
index f7c82665b05..f1f472aa426 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -487,6 +487,9 @@ get_insn_history_modifiers (const char **arg)
 
 	  switch (*args)
 	    {
+	    case 'a':
+	      modifiers |= DISASSEMBLY_OMIT_AUX_INSN;
+	      break;
 	    case 'm':
 	    case 's':
 	      modifiers |= DISASSEMBLY_SOURCE;
@@ -857,6 +860,8 @@ With a /m or /s modifier, source lines are included (if available).\n\
 With a /r modifier, raw instructions in hex are included.\n\
 With a /f modifier, function names are omitted.\n\
 With a /p modifier, current position markers are omitted.\n\
+With a /a modifier, omits output of auxiliary data, which is enabled \
+by default.\n\
 With no argument, disassembles ten more instructions after the previous \
 disassembly.\n\
 \"record instruction-history -\" disassembles ten instructions before a \
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v9 03/10] btrace: Enable auxiliary instructions in record function-call-history.
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
  2023-07-04 12:35 ` [PATCH v9 01/10] btrace: Introduce auxiliary instructions Felix Willgerodt
  2023-07-04 12:35 ` [PATCH v9 02/10] btrace: Enable auxiliary instructions in record instruction-history Felix Willgerodt
@ 2023-07-04 12:35 ` Felix Willgerodt
  2023-07-04 12:47   ` Eli Zaretskii
  2023-07-04 12:35 ` [PATCH v9 04/10] btrace: Handle stepping and goto for auxiliary instructions Felix Willgerodt
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:35 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Felix Willgerodt

Print the auxiliary data when a btrace_insn of type BTRACE_INSN_AUX
is encountered in the function-call-history.  Printing is
active by default, it can be silenced with the /a modifier.

This patch is in preparation for the new ptwrite feature, which is based on
auxiliary instructions.
---
 gdb/btrace.h        |  6 +++++-
 gdb/doc/gdb.texinfo |  5 +++--
 gdb/record-btrace.c | 21 +++++++++++++++++++++
 gdb/record.c        |  5 +++++
 gdb/record.h        |  5 ++++-
 5 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/gdb/btrace.h b/gdb/btrace.h
index dd80d3e6806..f6a8274bb16 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -105,7 +105,11 @@ enum btrace_function_flag
 
   /* The 'up' link points to a tail call.  This obviously only makes sense
      if bfun_up_links_to_ret is clear.  */
-  BFUN_UP_LINKS_TO_TAILCALL = (1 << 1)
+  BFUN_UP_LINKS_TO_TAILCALL = (1 << 1),
+
+  /* Indicates that at least one auxiliary instruction is in the current
+     function segment.  */
+  BFUN_CONTAINS_AUX = (1 << 2)
 };
 DEF_ENUM_FLAGS_TYPE (enum btrace_function_flag, btrace_function_flags);
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 5f15875f5dd..55a51449c7a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -8134,8 +8134,9 @@ that function, the source lines for this instruction sequence (if the
 @code{/l} modifier is specified), and the instructions numbers that form
 the sequence (if the @code{/i} modifier is specified).  The function names
 are indented to reflect the call stack depth if the @code{/c} modifier is
-specified.  The @code{/l}, @code{/i}, and @code{/c} modifiers can be given
-together.
+specified.  Printing auxiliary information is enabled by default and can be
+omitted with the @code{/a} modifier.  The @code{/l}, @code{/i}, @code{/a},
+and @code{/c} modifiers can be given together.
 
 @smallexample
 (@value{GDBP}) @b{list 1, 10}
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 36247d5b31d..02e71889eaf 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1159,6 +1159,23 @@ btrace_get_bfun_name (const struct btrace_function *bfun)
     return "??";
 }
 
+static void
+btrace_print_aux_insn (struct ui_out *uiout,
+		       const struct btrace_function *bfun,
+		       const struct btrace_thread_info *btinfo)
+{
+  for (const btrace_insn &insn : bfun->insn)
+    {
+      if (insn.iclass == BTRACE_INSN_AUX)
+	{
+	  uiout->text ("\t\t[");
+	  uiout->field_fmt ("aux-data", "%s",
+			    btinfo->aux_data.at (insn.aux_data_index).c_str ());
+	  uiout->text ("]\n");
+	}
+    }
+}
+
 /* Disassemble a section of the recorded function trace.  */
 
 static void
@@ -1234,6 +1251,10 @@ btrace_call_history (struct ui_out *uiout,
 	}
 
       uiout->text ("\n");
+
+      if (((flags & RECORD_DONT_PRINT_AUX) == 0)
+	  && ((bfun->flags & BFUN_CONTAINS_AUX) != 0))
+	btrace_print_aux_insn(uiout, bfun, btinfo);
     }
 }
 
diff --git a/gdb/record.c b/gdb/record.c
index f1f472aa426..c359613913d 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -640,6 +640,9 @@ get_call_history_modifiers (const char **arg)
 	    case 'c':
 	      modifiers |= RECORD_PRINT_INDENT_CALLS;
 	      break;
+	    case 'a':
+	      modifiers |= RECORD_DONT_PRINT_AUX;
+	      break;
 	    default:
 	      error (_("Invalid modifier: %c."), *args);
 	    }
@@ -884,6 +887,8 @@ Without modifiers, it prints the function name.\n\
 With a /l modifier, the source file and line number range is included.\n\
 With a /i modifier, the instruction number range is included.\n\
 With a /c modifier, the output is indented based on the call stack depth.\n\
+With a /a modifier, omits output of auxiliary data, which is enabled \
+by default.\n\
 With no argument, prints ten more lines after the previous ten-line print.\n\
 \"record function-call-history -\" prints ten lines before a previous ten-line \
 print.\n\
diff --git a/gdb/record.h b/gdb/record.h
index 166b5349988..ec06aaa7909 100644
--- a/gdb/record.h
+++ b/gdb/record.h
@@ -62,7 +62,10 @@ enum record_print_flag
   RECORD_PRINT_INSN_RANGE = (1 << 1),
 
   /* Indent based on call stack depth (if applicable).  */
-  RECORD_PRINT_INDENT_CALLS = (1 << 2)
+  RECORD_PRINT_INDENT_CALLS = (1 << 2),
+
+  /* Deactivate printing auxiliary data (if applicable).  */
+  RECORD_DONT_PRINT_AUX = (1 << 3)
 };
 DEF_ENUM_FLAGS_TYPE (enum record_print_flag, record_print_flags);
 
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v9 04/10] btrace: Handle stepping and goto for auxiliary instructions.
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
                   ` (2 preceding siblings ...)
  2023-07-04 12:35 ` [PATCH v9 03/10] btrace: Enable auxiliary instructions in record function-call-history Felix Willgerodt
@ 2023-07-04 12:35 ` Felix Willgerodt
  2023-07-04 12:35 ` [PATCH v9 05/10] python: Introduce gdb.RecordAuxiliary class Felix Willgerodt
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:35 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Felix Willgerodt

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

This patch is in preparation for the new ptwrite feature, which is based on
auxiliary instructions.
---
 gdb/record-btrace.c | 65 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 54 insertions(+), 11 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 02e71889eaf..c93b3d7c8de 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -2380,9 +2380,13 @@ record_btrace_single_step_forward (struct thread_info *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.  */
+     jump back to the instruction at which we started.  If we're stepping a
+     BTRACE_INSN_AUX instruction, print the auxiliary data and skip the
+     instruction.  */
+
   start = *replay;
-  do
+
+  for (;;)
     {
       unsigned int steps;
 
@@ -2394,8 +2398,23 @@ record_btrace_single_step_forward (struct thread_info *tp)
 	  *replay = start;
 	  return btrace_step_no_history ();
 	}
+
+      const struct btrace_insn *insn = btrace_insn_get (replay);
+      if (insn == nullptr)
+	continue;
+
+      /* If we're stepping a BTRACE_INSN_AUX instruction, print the auxiliary
+	 data and skip the instruction.  */
+      if (insn->iclass == BTRACE_INSN_AUX)
+	{
+	  gdb_printf ("[%s]\n",
+		      btinfo->aux_data.at (insn->aux_data_index).c_str ());
+	  continue;
+	}
+
+      /* We have an instruction, we are done.  */
+      break;
     }
-  while (btrace_insn_get (replay) == NULL);
 
   /* Determine the end of the instruction trace.  */
   btrace_insn_end (&end, btinfo);
@@ -2426,9 +2445,12 @@ record_btrace_single_step_backward (struct thread_info *tp)
 
   /* If we can't step any further, we reached the end of the history.
      Skip gaps during replay.  If we end up at a gap (at the beginning of
-     the trace), jump back to the instruction at which we started.  */
+     the trace), jump back to the instruction at which we started.
+     If we're stepping a BTRACE_INSN_AUX instruction, print the auxiliary
+     data and skip the instruction.  */
   start = *replay;
-  do
+
+  for (;;)
     {
       unsigned int steps;
 
@@ -2438,8 +2460,22 @@ record_btrace_single_step_backward (struct thread_info *tp)
 	  *replay = start;
 	  return btrace_step_no_history ();
 	}
+
+      const struct btrace_insn *insn = btrace_insn_get (replay);
+      if (insn == nullptr)
+	continue;
+
+      /* Check if we're stepping a BTRACE_INSN_AUX instruction and skip it.  */
+      if (insn->iclass == BTRACE_INSN_AUX)
+	{
+	  gdb_printf ("[%s]\n",
+		      btinfo->aux_data.at (insn->aux_data_index).c_str ());
+	  continue;
+	}
+
+      /* We have an instruction, we are done.  */
+      break;
     }
-  while (btrace_insn_get (replay) == NULL);
 
   /* Check if we're stepping a breakpoint.
 
@@ -2861,26 +2897,33 @@ 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);
 
-  /* 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
+     auxiliary instruction.  */
+  if (found == 0)
+    error (_("No such instruction."));
+
+  const struct btrace_insn *insn = btrace_insn_get (&it);
+  if (insn == NULL)
     error (_("No such instruction."));
+  if (insn->iclass == BTRACE_INSN_AUX)
+    error (_("Can't go to an auxiliary instruction."));
 
   record_btrace_set_replay (tp, &it);
 }
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v9 05/10] python: Introduce gdb.RecordAuxiliary class.
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
                   ` (3 preceding siblings ...)
  2023-07-04 12:35 ` [PATCH v9 04/10] btrace: Handle stepping and goto for auxiliary instructions Felix Willgerodt
@ 2023-07-04 12:35 ` Felix Willgerodt
  2023-07-04 12:52   ` Eli Zaretskii
  2023-07-04 12:35 ` [PATCH v9 06/10] python: Add clear() to gdb.Record Felix Willgerodt
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:35 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Felix Willgerodt

Auxiliary instructions are no real instructions and get their own object
class, similar to gaps. gdb.Record.instruction_history is now possibly a
list of gdb.RecordInstruction, gdb.RecordGap or gdb.RecordAuxiliary
objects.

This patch is in preparation for the new ptwrite feature, which is based on
auxiliary instructions.
---
 gdb/doc/python.texi           | 13 ++++++
 gdb/python/py-record-btrace.c | 81 +++++++++++++++++++++++++++++------
 gdb/python/py-record-btrace.h |  3 ++
 gdb/python/py-record.c        | 62 +++++++++++++++++++++++++--
 gdb/python/py-record.h        |  7 +++
 5 files changed, 150 insertions(+), 16 deletions(-)

diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 9a342f34bf0..b2140b1b8ea 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -4106,6 +4106,19 @@ the current recording method.
 A human readable string with the reason for the gap.
 @end defvar
 
+Some @value{GDBN} features write auxiliary information into the execution
+history.  This information is represented by a @code{gdb.RecordAuxiliary} object
+in the instruction list.  It has the following attributes:
+
+@defvar RecordAuxiliary.number
+An integer identifying this auxiliary.  @code{number} corresponds to the numbers
+seen in @code{record instruction-history} (@pxref{Process Record and Replay}).
+@end defvar
+
+@defvar RecordAuxiliary.data
+A string representation of the auxiliary data.
+@end defvar
+
 A @code{gdb.RecordFunctionSegment} object has the following attributes:
 
 @defvar RecordFunctionSegment.number
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 7978f3332c6..4a2a61e9b91 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -45,7 +45,8 @@ struct btpy_list_object {
   /* Stride size.  */
   Py_ssize_t step;
 
-  /* Either &BTPY_CALL_TYPE or &RECPY_INSN_TYPE.  */
+  /* Either &recpy_func_type, &recpy_insn_type, &recpy_aux_type or
+     &recpy_gap_type.  */
   PyTypeObject* element_type;
 };
 
@@ -141,15 +142,21 @@ btrace_func_from_recpy_func (const PyObject * const pyobject)
 }
 
 /* Looks at the recorded item with the number NUMBER and create a
-   gdb.RecordInstruction or gdb.RecordGap object for it accordingly.  */
+   gdb.RecordInstruction, gdb.RecordGap or gdb.RecordAuxiliary object
+   for it accordingly.  */
 
 static PyObject *
-btpy_insn_or_gap_new (thread_info *tinfo, Py_ssize_t number)
+btpy_item_new (thread_info *tinfo, Py_ssize_t number)
 {
   btrace_insn_iterator iter;
   int err_code;
 
-  btrace_find_insn_by_number (&iter, &tinfo->btrace, number);
+  if (btrace_find_insn_by_number (&iter, &tinfo->btrace, number) == 0)
+    {
+      PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
+      return nullptr;
+    }
+
   err_code = btrace_insn_get_error (&iter);
 
   if (err_code != 0)
@@ -163,6 +170,12 @@ btpy_insn_or_gap_new (thread_info *tinfo, Py_ssize_t number)
       return recpy_gap_new (err_code, err_string, number);
     }
 
+  const struct btrace_insn *insn = btrace_insn_get (&iter);
+  gdb_assert (insn != nullptr);
+
+  if (insn->iclass == BTRACE_INSN_AUX)
+    return recpy_aux_new (tinfo, RECORD_METHOD_BTRACE, number);
+
   return recpy_insn_new (tinfo, RECORD_METHOD_BTRACE, number);
 }
 
@@ -424,6 +437,48 @@ recpy_bt_func_next (PyObject *self, void *closure)
 			 RECORD_METHOD_BTRACE, func->next);
 }
 
+/* Implementation of Auxiliary.data [str] for btrace.  */
+
+PyObject *
+recpy_bt_aux_data (PyObject *self, void *closure)
+{
+  const btrace_insn *insn;
+  const recpy_element_object *obj;
+  thread_info *tinfo;
+  btrace_insn_iterator iter;
+
+  if (Py_TYPE (self) != &recpy_aux_type)
+    {
+      PyErr_Format (gdbpy_gdb_error, _("Must be a gdb.Auxiliary."));
+      return NULL;
+    }
+
+  obj = (const recpy_element_object *) self;
+  tinfo = obj->thread;
+
+  if (tinfo == NULL || btrace_is_empty (tinfo))
+    {
+      PyErr_Format (gdbpy_gdb_error, _("No such auxiliary object."));
+      return NULL;
+    }
+
+  if (btrace_find_insn_by_number (&iter, &tinfo->btrace, obj->number) == 0)
+    {
+      PyErr_Format (gdbpy_gdb_error, _("No such auxiliary object."));
+      return NULL;
+    }
+
+  insn = btrace_insn_get (&iter);
+  if (insn == NULL)
+    {
+      PyErr_Format (gdbpy_gdb_error, _("Not a valid auxiliary object."));
+      return NULL;
+    }
+
+  return PyUnicode_FromString
+    (iter.btinfo->aux_data.at (insn->aux_data_index).c_str ());
+}
+
 /* Implementation of BtraceList.__len__ (self) -> int.  */
 
 static Py_ssize_t
@@ -440,8 +495,9 @@ btpy_list_length (PyObject *self)
 }
 
 /* Implementation of
-   BtraceList.__getitem__ (self, key) -> BtraceInstruction and
-   BtraceList.__getitem__ (self, key) -> BtraceFunctionCall.  */
+   BtraceList.__getitem__ (self, key) -> BtraceInstruction,
+   BtraceList.__getitem__ (self, key) -> BtraceFunctionCall,
+   BtraceList.__getitem__ (self, key) -> BtraceAuxiliary.  */
 
 static PyObject *
 btpy_list_item (PyObject *self, Py_ssize_t index)
@@ -455,10 +511,10 @@ btpy_list_item (PyObject *self, Py_ssize_t index)
 
   number = obj->first + (obj->step * index);
 
-  if (obj->element_type == &recpy_insn_type)
-    return recpy_insn_new (obj->thread, RECORD_METHOD_BTRACE, number);
-  else
+  if (obj->element_type == &recpy_func_type)
     return recpy_func_new (obj->thread, RECORD_METHOD_BTRACE, number);
+  else
+    return btpy_item_new (obj->thread, number);
 }
 
 /* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList.  */
@@ -645,8 +701,7 @@ recpy_bt_replay_position (PyObject *self, void *closure)
   if (tinfo->btrace.replay == NULL)
     Py_RETURN_NONE;
 
-  return btpy_insn_or_gap_new (tinfo,
-			       btrace_insn_number (tinfo->btrace.replay));
+  return btpy_item_new (tinfo, btrace_insn_number (tinfo->btrace.replay));
 }
 
 /* Implementation of
@@ -668,7 +723,7 @@ recpy_bt_begin (PyObject *self, void *closure)
     Py_RETURN_NONE;
 
   btrace_insn_begin (&iterator, &tinfo->btrace);
-  return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator));
+  return btpy_item_new (tinfo, btrace_insn_number (&iterator));
 }
 
 /* Implementation of
@@ -690,7 +745,7 @@ recpy_bt_end (PyObject *self, void *closure)
     Py_RETURN_NONE;
 
   btrace_insn_end (&iterator, &tinfo->btrace);
-  return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator));
+  return btpy_item_new (tinfo, btrace_insn_number (&iterator));
 }
 
 /* Implementation of
diff --git a/gdb/python/py-record-btrace.h b/gdb/python/py-record-btrace.h
index 0af8153b715..0ca3da8e86f 100644
--- a/gdb/python/py-record-btrace.h
+++ b/gdb/python/py-record-btrace.h
@@ -88,4 +88,7 @@ extern PyObject *recpy_bt_func_prev (PyObject *self, void *closure);
 /* Implementation of RecordFunctionSegment.next [RecordFunctionSegment].  */
 extern PyObject *recpy_bt_func_next (PyObject *self, void *closure);
 
+/* Implementation of RecordAuxiliary.decoded [str].  */
+extern PyObject *recpy_bt_aux_data (PyObject *self, void *closure);
+
 #endif /* PYTHON_PY_RECORD_BTRACE_H */
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index c96c649b29c..c093cdaf3d6 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -49,6 +49,12 @@ static PyTypeObject recpy_gap_type = {
   PyVarObject_HEAD_INIT (NULL, 0)
 };
 
+/* Python RecordAuxiliary type.  */
+
+PyTypeObject recpy_aux_type = {
+  PyVarObject_HEAD_INIT (nullptr, 0)
+};
+
 /* Python RecordGap object.  */
 struct recpy_gap_object
 {
@@ -390,8 +396,8 @@ recpy_element_hash (PyObject *self)
   return obj->number;
 }
 
-/* Implementation of operator == and != of RecordInstruction and
-   RecordFunctionSegment.  */
+/* Implementation of operator == and != of RecordInstruction,
+   RecordFunctionSegment and RecordAuxiliary.  */
 
 static PyObject *
 recpy_element_richcompare (PyObject *self, PyObject *other, int op)
@@ -479,6 +485,38 @@ recpy_gap_reason_string (PyObject *self, void *closure)
   return PyUnicode_FromString (obj->reason_string);
 }
 
+/* Create a new gdb.Auxiliary object.  */
+
+PyObject *
+recpy_aux_new (thread_info *thread, enum record_method method,
+	       Py_ssize_t number)
+{
+  recpy_element_object * const obj = PyObject_New (recpy_element_object,
+						   &recpy_aux_type);
+
+  if (obj == NULL)
+   return NULL;
+
+  obj->thread = thread;
+  obj->method = method;
+  obj->number = number;
+
+  return (PyObject *) obj;
+}
+
+/* Implementation of Auxiliary.data [buffer].  */
+
+static PyObject *
+recpy_aux_data (PyObject *self, void *closure)
+{
+  const recpy_element_object * const obj = (recpy_element_object *) self;
+
+  if (obj->method == RECORD_METHOD_BTRACE)
+    return recpy_bt_aux_data (self, closure);
+
+  return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
 /* Record method list.  */
 
 static PyMethodDef recpy_record_methods[] = {
@@ -544,6 +582,14 @@ static gdb_PyGetSetDef recpy_gap_getset[] = {
   { NULL }
 };
 
+/* RecordAuxiliary member list.  */
+
+static gdb_PyGetSetDef recpy_aux_getset[] = {
+  { "number", recpy_element_number, nullptr, "element number", nullptr},
+  { "data", recpy_aux_data, nullptr, "data", nullptr},
+  { nullptr }
+};
+
 /* Sets up the record API in the gdb module.  */
 
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
@@ -583,10 +629,20 @@ gdbpy_initialize_record (void)
   recpy_gap_type.tp_doc = "GDB recorded gap object";
   recpy_gap_type.tp_getset = recpy_gap_getset;
 
+  recpy_aux_type.tp_new = PyType_GenericNew;
+  recpy_aux_type.tp_flags = Py_TPFLAGS_DEFAULT;
+  recpy_aux_type.tp_basicsize = sizeof (recpy_element_object);
+  recpy_aux_type.tp_name = "gdb.RecordAuxiliary";
+  recpy_aux_type.tp_doc = "GDB recorded auxiliary object";
+  recpy_aux_type.tp_getset = recpy_aux_getset;
+  recpy_aux_type.tp_richcompare = recpy_element_richcompare;
+  recpy_aux_type.tp_hash = recpy_element_hash;
+
   if (PyType_Ready (&recpy_record_type) < 0
       || PyType_Ready (&recpy_insn_type) < 0
       || PyType_Ready (&recpy_func_type) < 0
-      || PyType_Ready (&recpy_gap_type) < 0)
+      || PyType_Ready (&recpy_gap_type) < 0
+      || PyType_Ready (&recpy_aux_type) < 0)
     return -1;
   else
     return 0;
diff --git a/gdb/python/py-record.h b/gdb/python/py-record.h
index 6eec71e06e7..63e59798a02 100644
--- a/gdb/python/py-record.h
+++ b/gdb/python/py-record.h
@@ -59,6 +59,9 @@ extern PyTypeObject recpy_insn_type;
 /* Python RecordFunctionSegment type.  */
 extern PyTypeObject recpy_func_type;
 
+/* Python RecordAuxiliary type.  */
+extern PyTypeObject recpy_aux_type;
+
 /* Create a new gdb.RecordInstruction object.  */
 extern PyObject *recpy_insn_new (thread_info *thread, enum record_method method,
 				 Py_ssize_t number);
@@ -71,4 +74,8 @@ extern PyObject *recpy_func_new (thread_info *thread, enum record_method method,
 extern PyObject *recpy_gap_new (int reason_code, const char *reason_string,
 				Py_ssize_t number);
 
+/* Create a new gdb.RecordGap object.  */
+extern PyObject *recpy_aux_new (thread_info *thread, enum record_method method,
+				Py_ssize_t number);
+
 #endif /* PYTHON_PY_RECORD_H */
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v9 06/10] python: Add clear() to gdb.Record.
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
                   ` (4 preceding siblings ...)
  2023-07-04 12:35 ` [PATCH v9 05/10] python: Introduce gdb.RecordAuxiliary class Felix Willgerodt
@ 2023-07-04 12:35 ` Felix Willgerodt
  2023-07-04 12:46   ` Eli Zaretskii
  2023-07-06 16:11   ` Tom Tromey
  2023-07-04 12:35 ` [PATCH v9 07/10] btrace, gdbserver: Add ptwrite to btrace_config_pt Felix Willgerodt
                   ` (4 subsequent siblings)
  10 siblings, 2 replies; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:35 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Felix Willgerodt

This function allows to clear the trace data from python, forcing to
re-decode the trace for successive commands.
This will be used in future ptwrite patches, to trigger re-decoding when
the ptwrite filter changes.
---
 gdb/doc/python.texi                           |  5 +++++
 gdb/python/py-record-btrace.c                 | 13 +++++++++++++
 gdb/python/py-record-btrace.h                 |  3 +++
 gdb/python/py-record.c                        | 16 ++++++++++++++++
 gdb/testsuite/gdb.python/py-record-btrace.exp |  4 ++++
 5 files changed, 41 insertions(+)

diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index b2140b1b8ea..e0afa68541a 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -4051,6 +4051,11 @@ A @code{gdb.Record} object has the following methods:
 Move the replay position to the given @var{instruction}.
 @end defun
 
+@defun Record.clear ()
+Clear the trace data of the current recording.  This forces re-decoding of the
+trace for successive commands.
+@end defun
+
 The common @code{gdb.Instruction} class that recording method specific
 instruction objects inherit from, has the following attributes:
 
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 4a2a61e9b91..7e5bd2c401e 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -845,6 +845,19 @@ recpy_bt_goto (PyObject *self, PyObject *args)
   Py_RETURN_NONE;
 }
 
+/* Implementation of BtraceRecord.clear (self) -> None.  */
+
+PyObject *
+recpy_bt_clear (PyObject *self, PyObject *args)
+{
+  const recpy_record_object * const record = (recpy_record_object *) self;
+  thread_info *const tinfo = record->thread;
+
+  btrace_clear (tinfo);
+
+  Py_RETURN_NONE;
+}
+
 /* BtraceList methods.  */
 
 static PyMethodDef btpy_list_methods[] =
diff --git a/gdb/python/py-record-btrace.h b/gdb/python/py-record-btrace.h
index 0ca3da8e86f..785999e29e3 100644
--- a/gdb/python/py-record-btrace.h
+++ b/gdb/python/py-record-btrace.h
@@ -31,6 +31,9 @@ extern PyObject *recpy_bt_format (PyObject *self, void *closure);
 /* Implementation of record.goto (instruction) -> None.  */
 extern PyObject *recpy_bt_goto (PyObject *self, PyObject *value);
 
+/* Implementation of BtraceRecord.clear (self) -> None.  */
+extern PyObject *recpy_bt_clear (PyObject *self, PyObject *args);
+
 /* Implementation of record.instruction_history [list].  */
 extern PyObject *recpy_bt_instruction_history (PyObject *self, void *closure);
 
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index c093cdaf3d6..7824dd25953 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -115,6 +115,19 @@ recpy_goto (PyObject *self, PyObject *value)
   return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
 }
 
+/* Implementation of record.clear () -> None.  */
+
+static PyObject *
+recpy_clear (PyObject *self, PyObject *value)
+{
+  const recpy_record_object * const obj = (recpy_record_object *) self;
+
+  if (obj->method == RECORD_METHOD_BTRACE)
+    return recpy_bt_clear (self, value);
+
+  return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
 /* Implementation of record.replay_position [instruction]  */
 
 static PyObject *
@@ -523,6 +536,9 @@ static PyMethodDef recpy_record_methods[] = {
   { "goto", recpy_goto, METH_VARARGS,
     "goto (instruction|function_call) -> None.\n\
 Rewind to given location."},
+  { "clear", recpy_clear, METH_VARARGS,
+    "clear () -> None.\n\
+Clears the trace."},
   { NULL }
 };
 
diff --git a/gdb/testsuite/gdb.python/py-record-btrace.exp b/gdb/testsuite/gdb.python/py-record-btrace.exp
index bd397d3c974..fd45891fdfa 100644
--- a/gdb/testsuite/gdb.python/py-record-btrace.exp
+++ b/gdb/testsuite/gdb.python/py-record-btrace.exp
@@ -144,6 +144,10 @@ with_test_prefix "instruction " {
     gdb_test "python print(i.decoded)" ".*"
     gdb_test "python print(i.size)" "$decimal"
     gdb_test "python print(i.is_speculative)" "False"
+    gdb_test_no_output "python r.clear()"
+    gdb_test "python insn = r.instruction_history"
+    gdb_test_no_output "python i = insn\[0\]"
+    gdb_test "python print(i.size)" "$decimal"
 }
 
 with_test_prefix "function call" {
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v9 07/10] btrace, gdbserver: Add ptwrite to btrace_config_pt.
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
                   ` (5 preceding siblings ...)
  2023-07-04 12:35 ` [PATCH v9 06/10] python: Add clear() to gdb.Record Felix Willgerodt
@ 2023-07-04 12:35 ` Felix Willgerodt
  2023-07-04 12:49   ` Eli Zaretskii
  2023-07-04 12:35 ` [PATCH v9 08/10] btrace, linux: Enable ptwrite packets Felix Willgerodt
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:35 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Felix Willgerodt

This enables gdb and gdbserver to communicate about ptwrite support.  If
ptwrite support would be enabled unconditionally, GDBs with older libipt
versions would break.
---
 gdb/btrace.c                 |  8 +++++++-
 gdb/doc/gdb.texinfo          | 21 +++++++++++++++++++++
 gdb/features/btrace-conf.dtd |  1 +
 gdb/remote.c                 | 33 +++++++++++++++++++++++++++++++++
 gdbserver/linux-low.cc       |  3 +++
 gdbserver/server.cc          | 18 ++++++++++++++++++
 gdbsupport/btrace-common.h   |  6 ++++++
 7 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/gdb/btrace.c b/gdb/btrace.c
index 2c20763b570..6cbb53b01f1 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -2273,7 +2273,7 @@ parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser,
 			  std::vector<gdb_xml_value> &attributes)
 {
   struct btrace_config *conf;
-  struct gdb_xml_value *size;
+  struct gdb_xml_value *size, *ptwrite;
 
   conf = (struct btrace_config *) user_data;
   conf->format = BTRACE_FORMAT_PT;
@@ -2282,10 +2282,16 @@ parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser,
   size = xml_find_attribute (attributes, "size");
   if (size != NULL)
     conf->pt.size = (unsigned int) *(ULONGEST *) size->value.get ();
+
+  ptwrite = xml_find_attribute (attributes, "ptwrite");
+  if (ptwrite != nullptr)
+    conf->pt.ptwrite = (bool) *(ULONGEST *) ptwrite->value.get ();
 }
 
 static const struct gdb_xml_attribute btrace_conf_pt_attributes[] = {
   { "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
+  { "ptwrite", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_enum,
+    gdb_xml_enums_boolean },
   { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 55a51449c7a..cf06eb4bcd7 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -43933,6 +43933,11 @@ These are the currently defined stub features and their properties:
 @tab @samp{-}
 @tab Yes
 
+@item @samp{Qbtrace-conf:pt:ptwrite}
+@tab Yes
+@tab @samp{-}
+@tab Yes
+
 @item @samp{QNonStop}
 @tab No
 @tab @samp{-}
@@ -44244,6 +44249,9 @@ The remote stub understands the @samp{Qbtrace-conf:bts:size} packet.
 @item Qbtrace-conf:pt:size
 The remote stub understands the @samp{Qbtrace-conf:pt:size} packet.
 
+@item Qbtrace-conf:pt:ptwrite
+The remote stub understands the @samp{Qbtrace-conf:pt:ptwrite} packet.
+
 @item swbreak
 The remote stub reports the @samp{swbreak} stop reason for memory
 breakpoints.
@@ -44751,6 +44759,18 @@ The ring buffer size has been set.
 A badly formed request or an error was encountered.
 @end table
 
+@item Qbtrace-conf:pt:ptwrite=@var{(yes|no)}
+Indicate support for @code{PTWRITE} packets.  This allows for backwards
+compatibility.
+
+Reply:
+@table @samp
+@item OK
+The ptwrite config parameter has been set.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
 @end table
 
 @node Architecture-Specific Protocol Details
@@ -47399,6 +47419,7 @@ The formal DTD for the branch trace configuration format is given below:
 
 <!ELEMENT pt	EMPTY>
 <!ATTLIST pt	size	CDATA	#IMPLIED>
+<!ATTLIST pt	ptwrite	(yes | no)	#IMPLIED>
 @end smallexample
 
 @include agentexpr.texi
diff --git a/gdb/features/btrace-conf.dtd b/gdb/features/btrace-conf.dtd
index 3fbe3a4dc32..7aeaa4695e1 100644
--- a/gdb/features/btrace-conf.dtd
+++ b/gdb/features/btrace-conf.dtd
@@ -12,3 +12,4 @@
 
 <!ELEMENT pt	EMPTY>
 <!ATTLIST pt	size	CDATA	#IMPLIED>
+<!ATTLIST pt	ptwrite	(yes | no) #IMPLIED>
diff --git a/gdb/remote.c b/gdb/remote.c
index 7e3d6adfe4f..095aa630236 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -286,6 +286,9 @@ enum {
   /* Support for the Qbtrace-conf:pt:size packet.  */
   PACKET_Qbtrace_conf_pt_size,
 
+  /* Support for the Qbtrace-conf:pt:ptwrite packet.  */
+  PACKET_Qbtrace_conf_pt_ptwrite,
+
   /* Support for exec events.  */
   PACKET_exec_event_feature,
 
@@ -5597,6 +5600,8 @@ static const struct protocol_feature remote_protocol_features[] = {
     PACKET_exec_event_feature },
   { "Qbtrace-conf:pt:size", PACKET_DISABLE, remote_supported_packet,
     PACKET_Qbtrace_conf_pt_size },
+  { "Qbtrace-conf:pt:ptwrite", PACKET_DISABLE, remote_supported_packet,
+    PACKET_Qbtrace_conf_pt_ptwrite },
   { "vContSupported", PACKET_DISABLE, remote_supported_packet, PACKET_vContSupported },
   { "QThreadEvents", PACKET_DISABLE, remote_supported_packet, PACKET_QThreadEvents },
   { "no-resumed", PACKET_DISABLE, remote_supported_packet, PACKET_no_resumed },
@@ -14211,6 +14216,31 @@ remote_target::btrace_sync_conf (const btrace_config *conf)
 
       rs->btrace_config.pt.size = conf->pt.size;
     }
+
+  if ((m_features.packet_support (PACKET_Qbtrace_conf_pt_ptwrite)
+       == PACKET_ENABLE)
+	&& conf->pt.ptwrite != rs->btrace_config.pt.ptwrite)
+    {
+      pos = buf;
+      const char *ptw = conf->pt.ptwrite ? "yes" : "no";
+      const char *name
+	= packets_descriptions[PACKET_Qbtrace_conf_pt_ptwrite].name;
+      pos += xsnprintf (pos, endbuf - pos, "%s=\"%s\"", name, ptw);
+
+      putpkt (buf);
+      getpkt (&rs->buf, 0);
+
+      if (m_features.packet_ok (buf, PACKET_Qbtrace_conf_pt_ptwrite)
+	  == PACKET_ERROR)
+	{
+	  if (buf[0] == 'E' && buf[1] == '.')
+	    error (_("Failed to sync ptwrite config: %s"), buf + 2);
+	  else
+	    error (_("Failed to sync ptwrite config."));
+	}
+
+      rs->btrace_config.pt.ptwrite = conf->pt.ptwrite;
+    }
 }
 
 /* Read TP's btrace configuration from the target and store it into CONF.  */
@@ -15390,6 +15420,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (PACKET_Qbtrace_conf_pt_size, "Qbtrace-conf:pt:size",
 			 "btrace-conf-pt-size", 0);
 
+  add_packet_config_cmd (PACKET_Qbtrace_conf_pt_ptwrite, "Qbtrace-conf:pt:ptwrite",
+			 "btrace-conf-pt-ptwrite", 0);
+
   add_packet_config_cmd (PACKET_vContSupported, "vContSupported",
 			 "verbose-resume-supported", 0);
 
diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc
index 8ab16698632..69471b9998e 100644
--- a/gdbserver/linux-low.cc
+++ b/gdbserver/linux-low.cc
@@ -6876,6 +6876,9 @@ linux_process_target::read_btrace_conf (const btrace_target_info *tinfo,
 	  string_xml_appendf (*buffer, "<pt");
 	  string_xml_appendf (*buffer, " size=\"0x%x\"", conf->pt.size);
 	  string_xml_appendf (*buffer, "/>\n");
+	  string_xml_appendf (*buffer, " ptwrite=\"%s\"",
+			     conf->pt.ptwrite ? "yes" : "no");
+	  string_xml_appendf (*buffer, "/>\n");
 	  break;
 	}
     }
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
index c57270175b4..f54095b9a37 100644
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -547,6 +547,23 @@ handle_btrace_conf_general_set (char *own_buf)
 
       current_btrace_conf.pt.size = (unsigned int) size;
     }
+  else if (strncmp (op, "pt:ptwrite=", strlen ("pt:ptwrite=")) == 0)
+    {
+      bool ptwrite;
+
+      op += strlen ("pt:ptwrite=");
+      if (strncmp (op, "\"yes\"", strlen ("\"yes\"")) == 0)
+	ptwrite = true;
+      else if (strncmp (op, "\"no\"", strlen ("\"no\"")) == 0)
+	ptwrite = false;
+      else
+	{
+	  strcpy (own_buf, "E.Bad ptwrite value.");
+	  return -1;
+	}
+
+      current_btrace_conf.pt.ptwrite = ptwrite;
+    }
   else
     {
       strcpy (own_buf, "E.Bad Qbtrace configuration option.");
@@ -2146,6 +2163,7 @@ supported_btrace_packets (char *buf)
   strcat (buf, ";Qbtrace-conf:bts:size+");
   strcat (buf, ";Qbtrace:pt+");
   strcat (buf, ";Qbtrace-conf:pt:size+");
+  strcat (buf, ";Qbtrace-conf:pt:ptwrite+");
   strcat (buf, ";Qbtrace:off+");
   strcat (buf, ";qXfer:btrace:read+");
   strcat (buf, ";qXfer:btrace-conf:read+");
diff --git a/gdbsupport/btrace-common.h b/gdbsupport/btrace-common.h
index e287c93a6c1..03cc60648e9 100644
--- a/gdbsupport/btrace-common.h
+++ b/gdbsupport/btrace-common.h
@@ -117,6 +117,12 @@ struct btrace_config_pt
      This is unsigned int and not size_t since it is registered as
      control variable for "set record btrace pt buffer-size".  */
   unsigned int size;
+
+  /* Configuration bit for ptwrite packets.
+
+     If both gdb and gdbserver support this, gdb will try to enable ptwrite
+     packets when tracing is started.  */
+  bool ptwrite;
 };
 
 /* A branch tracing configuration.
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v9 08/10] btrace, linux: Enable ptwrite packets.
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
                   ` (6 preceding siblings ...)
  2023-07-04 12:35 ` [PATCH v9 07/10] btrace, gdbserver: Add ptwrite to btrace_config_pt Felix Willgerodt
@ 2023-07-04 12:35 ` Felix Willgerodt
  2023-07-04 12:35 ` [PATCH v9 09/10] btrace, python: Enable ptwrite filter registration Felix Willgerodt
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:35 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Felix Willgerodt

Enable ptwrite in the PT config, if it is supported by the kernel.
---
 gdb/nat/linux-btrace.c | 58 ++++++++++++++++++++++++++++++++++++++++++
 gdb/record-btrace.c    |  5 ++++
 2 files changed, 63 insertions(+)

diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c
index c5b3f1c93cf..689f4c46dd4 100644
--- a/gdb/nat/linux-btrace.c
+++ b/gdb/nat/linux-btrace.c
@@ -417,6 +417,57 @@ cpu_supports_bts (void)
     }
 }
 
+/* Read config bits.  */
+
+static bool
+linux_read_pt_config_bit (const std::string &feature, uint64_t *config_bit)
+{
+  std::string filename
+      = "/sys/bus/event_source/devices/intel_pt/format/" + feature;
+  gdb_file_up file = gdb_fopen_cloexec (filename.c_str (), "r");
+
+  if (file.get () == nullptr || config_bit == nullptr)
+    return false;
+
+  int found = fscanf (file.get (), "config:%lu", config_bit);
+
+  if (found != 1)
+    {
+      warning (_("Failed to determine config bit from %s."),
+	       filename.c_str ());
+      return false;
+    }
+
+  return true;
+}
+
+
+/* Check whether the linux target supports Intel Processor Trace PTWRITE.  */
+
+static bool
+linux_supports_ptwrite (uint64_t *config_bit)
+{
+  static const char filename[]
+      = "/sys/bus/event_source/devices/intel_pt/caps/ptwrite";
+  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
+
+  if (file.get () == nullptr)
+    return false;
+
+  int status, found = fscanf (file.get (), "%d", &status);
+
+  if (found != 1)
+    {
+      warning (_("Failed to determine ptwrite support from %s."), filename);
+      return false;
+    }
+
+  if (!linux_read_pt_config_bit ("ptw", config_bit))
+    return false;
+
+  return status == 1;
+}
+
 /* The perf_event_open syscall failed.  Try to print a helpful error
    message.  */
 
@@ -626,6 +677,13 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
   pt->attr.exclude_hv = 1;
   pt->attr.exclude_idle = 1;
 
+  uint64_t config_bit;
+  if (conf->ptwrite && linux_supports_ptwrite (&config_bit))
+    {
+      pt->attr.config |= 1 << config_bit;
+      tinfo->conf.pt.ptwrite = conf->ptwrite;
+    }
+
   errno = 0;
   scoped_fd fd (syscall (SYS_perf_event_open, &pt->attr, pid, -1, -1, 0));
   if (fd.get () < 0)
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index c93b3d7c8de..ad3160d42c5 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -3295,4 +3295,9 @@ to see the actual buffer size."), NULL, show_record_pt_buffer_size_value,
 
   record_btrace_conf.bts.size = 64 * 1024;
   record_btrace_conf.pt.size = 16 * 1024;
+#if (LIBIPT_VERSION >= 0x200)
+  record_btrace_conf.pt.ptwrite = true;
+#else
+  record_btrace_conf.pt.ptwrite = false;
+#endif
 }
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v9 09/10] btrace, python: Enable ptwrite filter registration.
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
                   ` (7 preceding siblings ...)
  2023-07-04 12:35 ` [PATCH v9 08/10] btrace, linux: Enable ptwrite packets Felix Willgerodt
@ 2023-07-04 12:35 ` Felix Willgerodt
  2023-07-06 16:31   ` Tom Tromey
  2023-07-04 12:36 ` [PATCH v9 10/10] btrace: Extend ptwrite event decoding Felix Willgerodt
  2023-07-06 16:37 ` [PATCH v9 00/10] Extensions for PTWRITE Tom Tromey
  10 siblings, 1 reply; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:35 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Felix Willgerodt

By default GDB will be printing the hex payload of the ptwrite package as
auxiliary information.  To customize this, the user can register a ptwrite
filter function in python, that takes the payload and the PC as arguments and
returns a string which will be printed instead.  Registering the filter
function is done using a factory pattern to make per-thread filtering easier.
---
 gdb/btrace.c                   |  4 ++
 gdb/btrace.h                   | 11 ++++
 gdb/data-directory/Makefile.in |  1 +
 gdb/extension-priv.h           |  5 ++
 gdb/extension.c                | 13 +++++
 gdb/extension.h                |  3 ++
 gdb/guile/guile.c              |  1 +
 gdb/python/lib/gdb/ptwrite.py  | 77 ++++++++++++++++++++++++++++
 gdb/python/py-record-btrace.c  | 91 ++++++++++++++++++++++++++++++++++
 gdb/python/python-internal.h   |  3 ++
 gdb/python/python.c            |  2 +
 11 files changed, 211 insertions(+)
 create mode 100644 gdb/python/lib/gdb/ptwrite.py

diff --git a/gdb/btrace.c b/gdb/btrace.c
index 6cbb53b01f1..157d9cc7c38 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -34,6 +34,7 @@
 #include "gdbsupport/rsp-low.h"
 #include "gdbcmd.h"
 #include "cli/cli-utils.h"
+#include "extension.h"
 #include "gdbarch.h"
 
 /* For maintenance commands.  */
@@ -1317,6 +1318,9 @@ ftrace_add_pt (struct btrace_thread_info *btinfo,
   uint64_t offset;
   int status;
 
+  /* Register the ptwrite filter.  */
+  apply_ext_lang_ptwrite_filter (btinfo);
+
   for (;;)
     {
       struct pt_insn insn;
diff --git a/gdb/btrace.h b/gdb/btrace.h
index f6a8274bb16..137ed0a0238 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -35,6 +35,7 @@
 #endif
 
 #include <vector>
+#include <string>
 
 struct thread_info;
 struct btrace_function;
@@ -352,6 +353,16 @@ struct btrace_thread_info
      displaying or stepping through the execution history.  */
   std::vector<std::string> aux_data;
 
+  /* Function pointer to the ptwrite callback.  Returns the string returned
+     by the ptwrite filter function.  */
+  gdb::optional<std::string> (*ptw_callback_fun) (const uint64_t payload,
+						  const uint64_t ip,
+						  const void *ptw_context)
+						    = nullptr;
+
+  /* Context for the ptw_callback_fun.  */
+  void *ptw_context = nullptr;
+
   /* The function level offset.  When added to each function's LEVEL,
      this normalizes the function levels such that the smallest level
      becomes zero.  */
diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
index a3775a4a666..388f198b8be 100644
--- a/gdb/data-directory/Makefile.in
+++ b/gdb/data-directory/Makefile.in
@@ -75,6 +75,7 @@ PYTHON_FILE_LIST = \
 	gdb/frames.py \
 	gdb/printing.py \
 	gdb/prompt.py \
+	gdb/ptwrite.py \
 	gdb/styling.py \
 	gdb/types.py \
 	gdb/unwinder.py \
diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h
index 3442302a0be..698cb1ab50e 100644
--- a/gdb/extension-priv.h
+++ b/gdb/extension-priv.h
@@ -184,6 +184,11 @@ struct extension_language_ops
      enum ext_lang_frame_args args_type,
      struct ui_out *out, int frame_low, int frame_high);
 
+  /* Used for registering the ptwrite filter to the current thread.  */
+  void (*apply_ptwrite_filter)
+    (const struct extension_language_defn *extlang,
+     struct btrace_thread_info *btinfo);
+
   /* Update values held by the extension language when OBJFILE is discarded.
      New global types must be created for every such value, which must then be
      updated to use the new types.
diff --git a/gdb/extension.c b/gdb/extension.c
index 65f3bab32a7..b03f4f27d48 100644
--- a/gdb/extension.c
+++ b/gdb/extension.c
@@ -551,6 +551,19 @@ apply_ext_lang_frame_filter (frame_info_ptr frame,
   return EXT_LANG_BT_NO_FILTERS;
 }
 
+/* Used for registering the ptwrite filter to the current thread.  */
+
+void
+apply_ext_lang_ptwrite_filter (btrace_thread_info *btinfo)
+{
+  for (const struct extension_language_defn *extlang : extension_languages)
+    {
+      if (extlang->ops != nullptr
+	  && extlang->ops->apply_ptwrite_filter != nullptr)
+	extlang->ops->apply_ptwrite_filter (extlang, btinfo);
+    }
+}
+
 /* Update values held by the extension language when OBJFILE is discarded.
    New global types must be created for every such value, which must then be
    updated to use the new types.
diff --git a/gdb/extension.h b/gdb/extension.h
index 2b0445133d3..16aa54cb247 100644
--- a/gdb/extension.h
+++ b/gdb/extension.h
@@ -295,6 +295,9 @@ extern enum ext_lang_bt_status apply_ext_lang_frame_filter
    enum ext_lang_frame_args args_type,
    struct ui_out *out, int frame_low, int frame_high);
 
+extern void apply_ext_lang_ptwrite_filter
+  (struct btrace_thread_info *btinfo);
+
 extern void preserve_ext_lang_values (struct objfile *, htab_t copied_types);
 
 extern const struct extension_language_defn *get_breakpoint_cond_ext_lang
diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c
index b45081fe1cc..1388dce5ba0 100644
--- a/gdb/guile/guile.c
+++ b/gdb/guile/guile.c
@@ -125,6 +125,7 @@ static const struct extension_language_ops guile_extension_ops =
   gdbscm_apply_val_pretty_printer,
 
   NULL, /* gdbscm_apply_frame_filter, */
+  NULL, /* gdbscm_load_ptwrite_filter, */
 
   gdbscm_preserve_values,
 
diff --git a/gdb/python/lib/gdb/ptwrite.py b/gdb/python/lib/gdb/ptwrite.py
new file mode 100644
index 00000000000..3be65fedb67
--- /dev/null
+++ b/gdb/python/lib/gdb/ptwrite.py
@@ -0,0 +1,77 @@
+# Ptwrite utilities.
+# Copyright (C) 2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""Utilities for working with ptwrite filters."""
+
+import gdb
+
+# _ptwrite_filter contains the per thread copies of the filter function.
+# The keys are tuples of inferior id and thread id.
+# The filter functions are created for each thread by calling the
+# _ptwrite_filter_factory.
+_ptwrite_filter = {}
+_ptwrite_filter_factory = None
+
+
+def _ptwrite_exit_handler(event):
+    """Exit handler to prune _ptwrite_filter on thread exit."""
+    _ptwrite_filter.pop(event.inferior_thread.ptid, None)
+
+
+gdb.events.thread_exited.connect(_ptwrite_exit_handler)
+
+
+def _clear_traces():
+    """Helper function to clear the trace of all threads."""
+    current_thread = gdb.selected_thread()
+
+    for inferior in gdb.inferiors():
+        for thread in inferior.threads():
+            thread.switch()
+            recording = gdb.current_recording()
+            if recording is not None:
+                recording.clear()
+
+    current_thread.switch()
+
+
+def register_filter_factory(filter_factory_):
+    """Register the ptwrite filter factory."""
+    if filter_factory_ is not None and not callable(filter_factory_):
+        raise TypeError("The filter factory must be callable or 'None'.")
+
+    # Clear the traces of all threads of all inferiors to force
+    # re-decoding with the new filter.
+    _clear_traces()
+
+    _ptwrite_filter.clear()
+    global _ptwrite_filter_factory
+    _ptwrite_filter_factory = filter_factory_
+
+
+def get_filter():
+    """Returns the filter of the current thread."""
+    thread = gdb.selected_thread()
+    key = thread.ptid
+
+    # Create a new filter for new threads.
+    if key not in _ptwrite_filter:
+        if _ptwrite_filter_factory is not None:
+            _ptwrite_filter[key] = _ptwrite_filter_factory(thread)
+        else:
+            return None
+
+    return _ptwrite_filter[key]
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 7e5bd2c401e..19fce7a622b 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -806,6 +806,97 @@ recpy_bt_function_call_history (PyObject *self, void *closure)
   return btpy_list_new (tinfo, first, last, 1, &recpy_func_type);
 }
 
+/* Helper function that calls PTW_FILTER with PAYLOAD and IP as arguments.
+   Returns the string that will be printed, if there is a filter to call.  */
+static gdb::optional<std::string>
+recpy_call_filter (const uint64_t payload, const uint64_t ip,
+		   const void *ptw_filter)
+{
+  gdb::optional<std::string> result;
+
+  gdb_assert (ptw_filter != nullptr);
+  if ((PyObject *) ptw_filter == Py_None)
+    return result;
+
+  gdbpy_enter enter_py;
+
+  gdbpy_ref<> py_payload (PyLong_FromUnsignedLongLong (payload));
+  gdbpy_ref<> py_ip (PyLong_FromUnsignedLongLong (ip));
+
+  if (ip == 0)
+    py_ip = gdbpy_ref<>::new_reference (Py_None);
+
+  gdbpy_ref<> py_result (PyObject_CallFunctionObjArgs ((PyObject *) ptw_filter,
+							py_payload.get (),
+							py_ip.get (),
+							nullptr));
+
+  if (PyErr_Occurred ())
+    {
+      gdbpy_print_stack ();
+      gdbpy_error (_("Couldn't call the ptwrite filter."));
+    }
+
+  /* Py_None is valid and results in no output.  */
+  if (py_result == Py_None)
+    {
+      result = "";
+      return result;
+    }
+
+  result = gdbpy_obj_to_string (py_result.get ()).get ();
+
+  if (PyErr_Occurred ())
+    {
+      gdbpy_print_stack ();
+      gdbpy_error (_("The ptwrite filter didn't return a string."));
+    }
+
+  return result;
+}
+
+/* Helper function returning the current ptwrite filter.  */
+
+static PyObject *
+get_ptwrite_filter ()
+{
+  gdbpy_ref<> module (PyImport_ImportModule ("gdb.ptwrite"));
+
+  if (PyErr_Occurred ())
+  {
+    gdbpy_print_stack ();
+    return nullptr;
+  }
+
+  /* We need to keep the reference count.  */
+  gdbpy_ref<> ptw_filter (PyObject_CallMethod (module.get (), "get_filter",
+					       nullptr));
+
+  if (PyErr_Occurred ())
+    {
+      gdbpy_print_stack ();
+      gdbpy_error (_("Couldn't get the ptwrite filter."));
+    }
+
+  return ptw_filter.get();
+}
+
+/* Used for registering the default ptwrite filter to the current thread.  A
+   pointer to this function is stored in the python extension interface.  */
+
+void
+gdbpy_load_ptwrite_filter (const struct extension_language_defn *extlang,
+			   struct btrace_thread_info *btinfo)
+{
+  gdb_assert (btinfo != nullptr);
+
+  gdbpy_enter enter_py;
+
+  btinfo->ptw_context = get_ptwrite_filter ();
+  if (btinfo->ptw_context != nullptr)
+    btinfo->ptw_callback_fun = &recpy_call_filter;
+}
+
 /* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None.  */
 
 PyObject *
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 93217375cc5..f44ad11cdf0 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -378,6 +378,9 @@ extern enum ext_lang_rc gdbpy_apply_val_pretty_printer
    struct ui_file *stream, int recurse,
    const struct value_print_options *options,
    const struct language_defn *language);
+extern void gdbpy_load_ptwrite_filter
+  (const struct extension_language_defn *extlang,
+   struct btrace_thread_info *btinfo);
 extern enum ext_lang_bt_status gdbpy_apply_frame_filter
   (const struct extension_language_defn *,
    frame_info_ptr frame, frame_filter_flags flags,
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 505fc4412d1..bd578a16fa5 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -153,6 +153,8 @@ static const struct extension_language_ops python_extension_ops =
 
   gdbpy_apply_frame_filter,
 
+  gdbpy_load_ptwrite_filter,
+
   gdbpy_preserve_values,
 
   gdbpy_breakpoint_has_cond,
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v9 10/10] btrace: Extend ptwrite event decoding.
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
                   ` (8 preceding siblings ...)
  2023-07-04 12:35 ` [PATCH v9 09/10] btrace, python: Enable ptwrite filter registration Felix Willgerodt
@ 2023-07-04 12:36 ` Felix Willgerodt
  2023-07-04 12:56   ` Eli Zaretskii
  2023-07-06 16:46   ` Tom Tromey
  2023-07-06 16:37 ` [PATCH v9 00/10] Extensions for PTWRITE Tom Tromey
  10 siblings, 2 replies; 33+ messages in thread
From: Felix Willgerodt @ 2023-07-04 12:36 UTC (permalink / raw)
  To: gdb-patches, markus.t.metzger, simark; +Cc: Felix Willgerodt

Call the ptwrite filter function whenever a ptwrite event is decoded.
The returned string is written to the aux_data string table and a
corresponding auxiliary instruction is appended to the function segment.
---
 gdb/NEWS                                  |   7 +
 gdb/btrace.c                              |  58 +++
 gdb/config.in                             |   3 +
 gdb/configure                             |  11 +
 gdb/doc/python.texi                       | 148 ++++++
 gdb/testsuite/gdb.btrace/i386-ptwrite.S   | 550 ++++++++++++++++++++++
 gdb/testsuite/gdb.btrace/ptwrite.c        |  39 ++
 gdb/testsuite/gdb.btrace/ptwrite.exp      | 202 ++++++++
 gdb/testsuite/gdb.btrace/x86_64-ptwrite.S | 544 +++++++++++++++++++++
 gdb/testsuite/lib/gdb.exp                 |  72 +++
 gdbsupport/common.m4                      |   2 +
 gdbsupport/config.in                      |   3 +
 gdbsupport/configure                      |  11 +
 13 files changed, 1650 insertions(+)
 create mode 100644 gdb/testsuite/gdb.btrace/i386-ptwrite.S
 create mode 100644 gdb/testsuite/gdb.btrace/ptwrite.c
 create mode 100644 gdb/testsuite/gdb.btrace/ptwrite.exp
 create mode 100644 gdb/testsuite/gdb.btrace/x86_64-ptwrite.S

diff --git a/gdb/NEWS b/gdb/NEWS
index fd42864c692..156e5c9c5f0 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -226,6 +226,13 @@ info main
 
 *** Changes in GDB 13
 
+* GDB now supports printing of ptwrite payloads from the Intel Processor
+  Trace during 'record instruction-history', 'record function-call-history'
+  and all stepping commands.  The payload is also accessible in Python as a
+  RecordAuxiliary object.  Printing is customizable via a ptwrite filter
+  function in Python.  By default, the raw ptwrite payload is printed for
+  each ptwrite that is encountered.
+
 * MI version 1 is deprecated, and will be removed in GDB 14.
 
 * GDB now supports dumping memory tag data for AArch64 MTE.  It also supports
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 157d9cc7c38..70ccc0951a3 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -43,6 +43,7 @@
 #include <inttypes.h>
 #include <ctype.h>
 #include <algorithm>
+#include <string>
 
 /* Command lists for btrace maintenance commands.  */
 static struct cmd_list_element *maint_btrace_cmdlist;
@@ -1253,6 +1254,57 @@ handle_pt_insn_events (struct btrace_thread_info *btinfo,
 		   bfun->insn_offset - 1, offset);
 
 	  break;
+#if defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE)
+	case ptev_ptwrite:
+	  {
+	    uint64_t ip = 0;
+	    gdb::optional<std::string> ptw_string;
+	    btrace_insn_flags flags = 0;
+
+	    /* Lookup the ip if available.  */
+	    if (event.ip_suppressed == 0)
+	      ip = event.variant.ptwrite.ip;
+
+	    if (btinfo->ptw_callback_fun != nullptr)
+	      ptw_string
+		= btinfo->ptw_callback_fun (event.variant.ptwrite.payload,
+					    ip, btinfo->ptw_context);
+
+	    if (ptw_string.has_value () && (*ptw_string).empty ())
+	      continue;
+
+	    if (!ptw_string.has_value ())
+	      *ptw_string = hex_string (event.variant.ptwrite.payload);
+
+	    btinfo->aux_data.emplace_back (std::move (*ptw_string));
+
+	    if (!btinfo->functions.empty ()
+		&& !btinfo->functions.back ().insn.empty ())
+	      flags = btinfo->functions.back ().insn.back ().flags;
+
+	    /* Update insn list with ptw payload insn.  */
+	    struct btrace_insn ptw_insn;
+	    ptw_insn.aux_data_index = btinfo->aux_data.size () - 1;
+	    ptw_insn.size = 0;
+	    ptw_insn.iclass = BTRACE_INSN_AUX;
+	    ptw_insn.flags = flags;
+
+	    if (ip != 0)
+	      bfun = ftrace_update_function (btinfo, ip);
+	    else
+	      {
+		if (btinfo->functions.empty ())
+		  bfun = ftrace_new_function (btinfo, NULL, NULL);
+		else
+		  bfun = &btinfo->functions.back ();
+	      }
+
+	    bfun->flags |= BFUN_CONTAINS_AUX;
+	    ftrace_update_insns (bfun, ptw_insn);
+
+	    break;
+	  }
+#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */
 	}
     }
 #endif /* defined (HAVE_PT_INSN_EVENT) */
@@ -2981,6 +3033,12 @@ pt_print_packet (const struct pt_packet *packet)
     case ppt_mnt:
       gdb_printf (("mnt %" PRIx64 ""), packet->payload.mnt.payload);
       break;
+
+#if defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE)
+    case ppt_ptw:
+      gdb_printf (("ptw %" PRIx64 ""), packet->payload.ptw.payload);
+      break;
+#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */
     }
 }
 
diff --git a/gdb/config.in b/gdb/config.in
index a7da88b92d7..9e6e59d73c3 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -460,6 +460,9 @@
 /* Define to 1 if `pl_tdname' is a member of `struct ptrace_lwpinfo'. */
 #undef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME
 
+/* Define to 1 if `variant.ptwrite' is a member of `struct pt_event'. */
+#undef HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE
+
 /* Define to 1 if `enabled' is a member of `struct pt_insn'. */
 #undef HAVE_STRUCT_PT_INSN_ENABLED
 
diff --git a/gdb/configure b/gdb/configure
index 5bb2a0795e5..778e69f74b9 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -25770,6 +25770,17 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+fi
+
+      ac_fn_c_check_member "$LINENO" "struct pt_event" "variant.ptwrite" "ac_cv_member_struct_pt_event_variant_ptwrite" "#include <intel-pt.h>
+"
+if test "x$ac_cv_member_struct_pt_event_variant_ptwrite" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE 1
+_ACEOF
+
+
 fi
 
       LIBS=$save_LIBS
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index e0afa68541a..410fda98058 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -7676,6 +7676,7 @@ registering objfile-specific pretty-printers and frame-filters.
 * gdb.printing::       Building and registering pretty-printers.
 * gdb.types::          Utilities for working with types.
 * gdb.prompt::         Utilities for prompt value substitution.
+* gdb.ptwrite::        Utilities for PTWRITE filter registration.
 @end menu
 
 @node gdb.printing
@@ -7866,3 +7867,150 @@ substitute_prompt ("frame: \f, args: \p@{print frame-arguments@}")
 "frame: main, args: scalars"
 @end smallexample
 @end table
+
+@node gdb.ptwrite
+@subsubsection gdb.ptwrite
+@cindex gdb.ptwrite
+
+This module provides additional functionality for recording programs that
+make use of the @code{PTWRITE} instruction.  @code{PTWRITE} is a x86
+instruction that allows to write values into the Intel Processor Trace
+(@pxref{Process Record and Replay}).
+The @value{NGCC} built-in functions for it are:
+@smallexample
+void __builtin_ia32_ptwrite32 (unsigned);
+void __builtin_ia32_ptwrite64 (unsigned long long);
+@end smallexample
+
+If an inferior uses the instruction, @value{GDBN} by default inserts the
+raw payload value as auxiliary information into the execution history.
+Auxiliary information is by default printed during
+@code{record instruction-history}, @code{record function-call-history},
+and all stepping commands, and is accessible in Python as a
+@code{RecordAuxiliary} object.
+
+@exdent Sample program:
+@smallexample
+@group
+void
+ptwrite64 (unsigned long long value)
+@{
+  __builtin_ia32_ptwrite64 (value);
+@}
+@end group
+
+@group
+int
+main (void)
+@{
+  ptwrite64 (0x42);
+  return 0; /* break here.  */
+@}
+@end group
+@end smallexample
+
+
+@exdent @value{GDBN} output after recording the sample program in pt format:
+@smallexample
+@group
+(gdb) record instruction-history 12,14
+12         0x0040074c <ptwrite64+16>:   ptwrite %rbx
+13         [0x42]
+14         0x00400751 <ptwrite64+21>:   mov -0x8(%rbp),%rbx
+(gdb) record function-call-history
+1       main
+2       ptwrite64
+                [0x42]
+3       main
+@end group
+@end smallexample
+
+The @code{gdb.ptwrite} module allows customizing the default output of
+@code{PTWRITE} auxiliary information.  A custom Python function can be
+registered as the @code{PTWRITE} filter function.  This function will be
+called with the @code{PTWRITE} payload and PC as arguments during trace
+decoding.  It can return a string, which will be printed by @value{GDBN}
+during the aforementioned commands, or @code{None}, resulting in no output.
+To register such a filter function, the user needs to provide a filter factory
+function, which returns a new filter function object to be called by GDB.
+
+@findex gdb.ptwrite.register_filter_factory
+@defun register_filter_factory (filter_factory)
+Used to register the @code{PTWRITE} filter factory.  This filter factory can
+be any callable object that accepts one argument, the current thread as
+a @code{gdb.InferiorThread}.
+It can return None or a callable.  This callable is the @code{PTWRITE} filter
+function for the specified thread.  If @code{None} is returned by the factory
+function, the default auxiliary information will be printed.
+@end defun
+
+@findex gdb.ptwrite.get_filter
+@defun get_filter ()
+Return the currently active @code{PTWRITE} filter function.
+@end defun
+
+An example:
+
+@smallexample
+@group
+(gdb) python-interactive
+>>> class my_filter():
+...    def __init__(self):
+...        self.var = 0
+...    def __call__(self, payload, ip):
+...        self.var += 1
+...        return f"counter: @{self.var@}, ip: @{ip:#x@}"
+...
+>>> def my_filter_factory(thread):
+...    if thread.global_num == 1:
+...        return my_filter()
+...    else:
+...        return None
+...
+>>> import gdb.ptwrite
+>>> gdb.ptwrite.register_filter_factory(my_filter_factory)
+>>>
+@end group
+
+@group
+(gdb) record function-call-history 59,64
+59      pthread_create@@GLIBC_2.2.5
+60      job()
+61      task(void*)
+62      ptwrite64(unsigned long)
+                [counter: 1, ip: 0x401156]
+63      task(void*)
+64      ptwrite32(unsigned int)
+                [counter: 2, ip: 0x40116c]
+@end group
+
+@group
+(gdb) info threads
+* 1    Thread 0x7ffff7fd8740 (LWP 25796) "ptw_threads" task ()
+    at bin/ptwrite/ptw_threads.c:45
+  2    Thread 0x7ffff6eb8700 (LWP 25797) "ptw_threads" task ()
+    at bin/ptwrite/ptw_threads.c:45
+@end group
+
+@group
+(gdb) thread 2
+[Switching to thread 2 (Thread 0x7ffff6eb8700 (LWP 25797))]
+#0  task (arg=0x0) at ptwrite_threads.c:45
+45        return NULL;
+@end group
+
+@group
+(gdb) record function-call-history 10,14
+10    start_thread
+11    task(void*)
+12    ptwrite64(unsigned long)
+              [0x42]
+13    task(void*)
+14    ptwrite32(unsigned int)
+              [0x43]
+@end group
+@end smallexample
+
+This @value{GDBN} feature is dependent on hardware and operating system
+support and requires the Intel Processor Trace decoder library in version
+2.0.0 or newer.
diff --git a/gdb/testsuite/gdb.btrace/i386-ptwrite.S b/gdb/testsuite/gdb.btrace/i386-ptwrite.S
new file mode 100644
index 00000000000..3e09bc938a1
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/i386-ptwrite.S
@@ -0,0 +1,550 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+   This file has been generated using gcc version 10.3.1 20210422
+   (Red Hat 10.3.1-1):
+   gcc -S -dA -g -m32 -mptwrite ptwrite.c -o i386-ptwrite.S.  */
+
+
+	.file	"ptwrite.c"
+	.text
+.Ltext0:
+	.globl	ptwrite1
+	.type	ptwrite1, @function
+ptwrite1:
+.LFB4021:
+	.file 1 "ptwrite.c"
+	# ptwrite.c:22:1
+	.loc 1 22 1
+	.cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+	pushl	%ebp
+	.cfi_def_cfa_offset 8
+	.cfi_offset 5, -8
+	movl	%esp, %ebp
+	.cfi_def_cfa_register 5
+	subl	$16, %esp
+	# ptwrite.c:23:3
+	.loc 1 23 3
+	movl	8(%ebp), %eax
+	movl	%eax, -4(%ebp)
+.LBB6:
+.LBB7:
+	.file 2 "/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h"
+	# /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3
+	.loc 2 307 3
+	movl	-4(%ebp), %eax
+	ptwrite	%eax
+	# /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1
+	.loc 2 308 1
+	nop
+.LBE7:
+.LBE6:
+	# ptwrite.c:24:1
+	.loc 1 24 1
+	nop
+	leave
+	.cfi_restore 5
+	.cfi_def_cfa 4, 4
+# SUCC: EXIT [always]
+	ret
+	.cfi_endproc
+.LFE4021:
+	.size	ptwrite1, .-ptwrite1
+	.globl	ptwrite2
+	.type	ptwrite2, @function
+ptwrite2:
+.LFB4022:
+	# ptwrite.c:28:1
+	.loc 1 28 1
+	.cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+	pushl	%ebp
+	.cfi_def_cfa_offset 8
+	.cfi_offset 5, -8
+	movl	%esp, %ebp
+	.cfi_def_cfa_register 5
+	subl	$16, %esp
+	# ptwrite.c:29:3
+	.loc 1 29 3
+	movl	8(%ebp), %eax
+	movl	%eax, -4(%ebp)
+.LBB8:
+.LBB9:
+	# /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3
+	.loc 2 307 3
+	movl	-4(%ebp), %eax
+	ptwrite	%eax
+	# /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1
+	.loc 2 308 1
+	nop
+.LBE9:
+.LBE8:
+	# ptwrite.c:30:1
+	.loc 1 30 1
+	nop
+	leave
+	.cfi_restore 5
+	.cfi_def_cfa 4, 4
+# SUCC: EXIT [always]
+	ret
+	.cfi_endproc
+.LFE4022:
+	.size	ptwrite2, .-ptwrite2
+	.globl	main
+	.type	main, @function
+main:
+.LFB4023:
+	# ptwrite.c:34:1
+	.loc 1 34 1
+	.cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+	pushl	%ebp
+	.cfi_def_cfa_offset 8
+	.cfi_offset 5, -8
+	movl	%esp, %ebp
+	.cfi_def_cfa_register 5
+	# ptwrite.c:35:3
+	.loc 1 35 3
+	pushl	$66
+	call	ptwrite1
+	addl	$4, %esp
+	# ptwrite.c:36:3
+	.loc 1 36 3
+	pushl	$67
+	call	ptwrite2
+	addl	$4, %esp
+	# ptwrite.c:38:10
+	.loc 1 38 10
+	movl	$0, %eax
+	# ptwrite.c:39:1
+	.loc 1 39 1
+	leave
+	.cfi_restore 5
+	.cfi_def_cfa 4, 4
+# SUCC: EXIT [always]
+	ret
+	.cfi_endproc
+.LFE4023:
+	.size	main, .-main
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x129	# Length of Compilation Unit Info
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x4	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF15	# DW_AT_producer: "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -m32 -mptwrite -mtune=generic -march=i686 -g"
+	.byte	0xc	# DW_AT_language
+	.long	.LASF16	# DW_AT_name: "ptwrite.c"
+	.long	.LASF17	# DW_AT_comp_dir: "gdb/gdb/testsuite/gdb.btrace"
+	.long	.Ltext0	# DW_AT_low_pc
+	.long	.Letext0-.Ltext0	# DW_AT_high_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+	.uleb128 0x2	# (DIE (0x25) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.ascii "int\0"	# DW_AT_name
+	.uleb128 0x3	# (DIE (0x2c) DW_TAG_base_type)
+	.byte	0x2	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.long	.LASF0	# DW_AT_name: "short int"
+	.uleb128 0x3	# (DIE (0x33) DW_TAG_base_type)
+	.byte	0x1	# DW_AT_byte_size
+	.byte	0x6	# DW_AT_encoding
+	.long	.LASF1	# DW_AT_name: "char"
+	.uleb128 0x3	# (DIE (0x3a) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.long	.LASF2	# DW_AT_name: "long long int"
+	.uleb128 0x3	# (DIE (0x41) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x4	# DW_AT_encoding
+	.long	.LASF3	# DW_AT_name: "float"
+	.uleb128 0x3	# (DIE (0x48) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF4	# DW_AT_name: "unsigned int"
+	.uleb128 0x3	# (DIE (0x4f) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.long	.LASF5	# DW_AT_name: "long int"
+	.uleb128 0x3	# (DIE (0x56) DW_TAG_base_type)
+	.byte	0x1	# DW_AT_byte_size
+	.byte	0x8	# DW_AT_encoding
+	.long	.LASF6	# DW_AT_name: "unsigned char"
+	.uleb128 0x3	# (DIE (0x5d) DW_TAG_base_type)
+	.byte	0x2	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF7	# DW_AT_name: "short unsigned int"
+	.uleb128 0x3	# (DIE (0x64) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF8	# DW_AT_name: "long unsigned int"
+	.uleb128 0x3	# (DIE (0x6b) DW_TAG_base_type)
+	.byte	0x1	# DW_AT_byte_size
+	.byte	0x6	# DW_AT_encoding
+	.long	.LASF9	# DW_AT_name: "signed char"
+	.uleb128 0x3	# (DIE (0x72) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF10	# DW_AT_name: "long long unsigned int"
+	.uleb128 0x3	# (DIE (0x79) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x4	# DW_AT_encoding
+	.long	.LASF11	# DW_AT_name: "double"
+	.uleb128 0x4	# (DIE (0x80) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF18	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (ptwrite.c)
+	.byte	0x21	# DW_AT_decl_line
+	.byte	0x1	# DW_AT_decl_column
+			# DW_AT_prototyped
+	.long	0x25	# DW_AT_type
+	.long	.LFB4023	# DW_AT_low_pc
+	.long	.LFE4023-.LFB4023	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_tail_call_sites
+	.uleb128 0x5	# (DIE (0x96) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF12	# DW_AT_name: "ptwrite2"
+	.byte	0x1	# DW_AT_decl_file (ptwrite.c)
+	.byte	0x1b	# DW_AT_decl_line
+	.byte	0x1	# DW_AT_decl_column
+			# DW_AT_prototyped
+	.long	.LFB4022	# DW_AT_low_pc
+	.long	.LFE4022-.LFB4022	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+	.long	0xd5	# DW_AT_sibling
+	.uleb128 0x6	# (DIE (0xac) DW_TAG_formal_parameter)
+	.long	.LASF14	# DW_AT_name: "value"
+	.byte	0x1	# DW_AT_decl_file (ptwrite.c)
+	.byte	0x1b	# DW_AT_decl_line
+	.byte	0xf	# DW_AT_decl_column
+	.long	0x25	# DW_AT_type
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 0
+	.uleb128 0x7	# (DIE (0xbb) DW_TAG_inlined_subroutine)
+	.long	0x114	# DW_AT_abstract_origin
+	.long	.LBB8	# DW_AT_low_pc
+	.long	.LBE8-.LBB8	# DW_AT_high_pc
+	.byte	0x1	# DW_AT_call_file (ptwrite.c)
+	.byte	0x1d	# DW_AT_call_line
+	.byte	0x3	# DW_AT_call_column
+	.uleb128 0x8	# (DIE (0xcb) DW_TAG_formal_parameter)
+	.long	0x11e	# DW_AT_abstract_origin
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -12
+	.byte	0	# end of children of DIE 0xbb
+	.byte	0	# end of children of DIE 0x96
+	.uleb128 0x5	# (DIE (0xd5) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF13	# DW_AT_name: "ptwrite1"
+	.byte	0x1	# DW_AT_decl_file (ptwrite.c)
+	.byte	0x15	# DW_AT_decl_line
+	.byte	0x1	# DW_AT_decl_column
+			# DW_AT_prototyped
+	.long	.LFB4021	# DW_AT_low_pc
+	.long	.LFE4021-.LFB4021	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+	.long	0x114	# DW_AT_sibling
+	.uleb128 0x6	# (DIE (0xeb) DW_TAG_formal_parameter)
+	.long	.LASF14	# DW_AT_name: "value"
+	.byte	0x1	# DW_AT_decl_file (ptwrite.c)
+	.byte	0x15	# DW_AT_decl_line
+	.byte	0xf	# DW_AT_decl_column
+	.long	0x25	# DW_AT_type
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 0
+	.uleb128 0x7	# (DIE (0xfa) DW_TAG_inlined_subroutine)
+	.long	0x114	# DW_AT_abstract_origin
+	.long	.LBB6	# DW_AT_low_pc
+	.long	.LBE6-.LBB6	# DW_AT_high_pc
+	.byte	0x1	# DW_AT_call_file (ptwrite.c)
+	.byte	0x17	# DW_AT_call_line
+	.byte	0x3	# DW_AT_call_column
+	.uleb128 0x8	# (DIE (0x10a) DW_TAG_formal_parameter)
+	.long	0x11e	# DW_AT_abstract_origin
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -12
+	.byte	0	# end of children of DIE 0xfa
+	.byte	0	# end of children of DIE 0xd5
+	.uleb128 0x9	# (DIE (0x114) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF19	# DW_AT_name: "_ptwrite32"
+	.byte	0x2	# DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h)
+	.value	0x131	# DW_AT_decl_line
+	.byte	0x1	# DW_AT_decl_column
+			# DW_AT_prototyped
+	.byte	0x3	# DW_AT_inline
+			# DW_AT_artificial
+	.uleb128 0xa	# (DIE (0x11e) DW_TAG_formal_parameter)
+	.ascii "__B\0"	# DW_AT_name
+	.byte	0x2	# DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h)
+	.value	0x131	# DW_AT_decl_line
+	.byte	0x16	# DW_AT_decl_column
+	.long	0x48	# DW_AT_type
+	.byte	0	# end of children of DIE 0x114
+	.byte	0	# end of children of DIE 0xb
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	# (abbrev code)
+	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x25	# (DW_AT_producer)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x13	# (DW_AT_language)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x1b	# (DW_AT_comp_dir)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x6	# (DW_FORM_data4)
+	.uleb128 0x10	# (DW_AT_stmt_list)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0	# DW_children_no
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x39	# (DW_AT_decl_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x27	# (DW_AT_prototyped)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x6	# (DW_FORM_data4)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2116	# (DW_AT_GNU_all_tail_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x39	# (DW_AT_decl_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x27	# (DW_AT_prototyped)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x6	# (DW_FORM_data4)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x39	# (DW_AT_decl_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	# (abbrev code)
+	.uleb128 0x1d	# (TAG: DW_TAG_inlined_subroutine)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x6	# (DW_FORM_data4)
+	.uleb128 0x58	# (DW_AT_call_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x59	# (DW_AT_call_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x57	# (DW_AT_call_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0x5	# (DW_FORM_data2)
+	.uleb128 0x39	# (DW_AT_decl_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x27	# (DW_AT_prototyped)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x20	# (DW_AT_inline)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x34	# (DW_AT_artificial)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0xa	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0x5	# (DW_FORM_data2)
+	.uleb128 0x39	# (DW_AT_decl_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x1c	# Length of Address Ranges Info
+	.value	0x2	# DWARF aranges version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x4	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 8 byte boundary
+	.value	0
+	.long	.Ltext0	# Address
+	.long	.Letext0-.Ltext0	# Length
+	.long	0
+	.long	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF2:
+	.string	"long long int"
+.LASF14:
+	.string	"value"
+.LASF19:
+	.string	"_ptwrite32"
+.LASF4:
+	.string	"unsigned int"
+.LASF17:
+	.string	"gdb/gdb/testsuite/gdb.btrace"
+.LASF18:
+	.string	"main"
+.LASF16:
+	.string	"ptwrite.c"
+.LASF8:
+	.string	"long unsigned int"
+.LASF10:
+	.string	"long long unsigned int"
+.LASF13:
+	.string	"ptwrite1"
+.LASF12:
+	.string	"ptwrite2"
+.LASF6:
+	.string	"unsigned char"
+.LASF1:
+	.string	"char"
+.LASF5:
+	.string	"long int"
+.LASF15:
+	.string	"GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -m32 -mptwrite -mtune=generic -march=i686 -g"
+.LASF11:
+	.string	"double"
+.LASF7:
+	.string	"short unsigned int"
+.LASF9:
+	.string	"signed char"
+.LASF3:
+	.string	"float"
+.LASF0:
+	.string	"short int"
+	.ident	"GCC: (GNU) 10.3.1 20210422 (Red Hat 10.3.1-1)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.btrace/ptwrite.c b/gdb/testsuite/gdb.btrace/ptwrite.c
new file mode 100644
index 00000000000..efa9e97b7df
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/ptwrite.c
@@ -0,0 +1,39 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <immintrin.h>
+
+void
+ptwrite1 (int value)
+{
+  _ptwrite32 (value);
+}
+
+void
+ptwrite2 (int value)
+{
+  _ptwrite32 (value);
+}
+
+int
+main (void)
+{
+  ptwrite1 (0x42);
+  ptwrite2 (0x43);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.btrace/ptwrite.exp b/gdb/testsuite/gdb.btrace/ptwrite.exp
new file mode 100644
index 00000000000..7878e7fc50d
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/ptwrite.exp
@@ -0,0 +1,202 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2023 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib gdb-python.exp
+
+require allow_btrace_ptw_tests allow_python_tests
+
+set opts {}
+
+if [info exists COMPILE] {
+    # make check RUNTESTFLAGS="gdb.btrace/ptwrite.exp COMPILE=1"
+    standard_testfile ptwrite.c
+    lappend opts debug additional_flags=-mptwrite
+} elseif {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} {
+    if {[is_amd64_regs_target]} {
+	standard_testfile x86_64-ptwrite.S
+    } else {
+	standard_testfile i386-ptwrite.S
+    }
+} else {
+    unsupported "target architecture not supported"
+    return -1
+}
+
+if [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] {
+    return -1
+}
+
+if { ![runto_main] } {
+    untested "failed to run to main"
+    return -1
+}
+
+### 1. Default testrun
+
+# Setup recording
+gdb_test_no_output "set record instruction-history-size unlimited"
+gdb_test_no_output "record btrace pt"
+gdb_test "next" ".*" "next"
+gdb_test "next" ".*" "next 2"
+
+with_test_prefix "Default" {
+    # Test record instruction-history
+    gdb_test "record instruction-history 1" [multi_line \
+	".*\[0-9\]+\t   $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	"\[0-9\]+\t   \\\[0x42\\\]" \
+	".*\[0-9\]+\t   $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	"\[0-9\]+\t   \\\[0x43\\\].*" \
+	]
+
+    gdb_test "record instruction-history /a 1" [multi_line \
+	".*\[0-9\]+\t   $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	".*\[0-9\]+\t   $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+.*" \
+	]
+
+    # Test function call history
+    gdb_test "record function-call-history 1,4" [multi_line \
+	"1\tmain" \
+	"2\tptwrite1" \
+	"\t\t\\\[0x42\\\]" \
+	"3\tmain" \
+	"4\tptwrite2" \
+	"\t\t\\\[0x43\\\]" \
+	]
+
+    gdb_test "record function-call-history /a 1,4" [multi_line \
+	"1\tmain" \
+	"2\tptwrite1" \
+	"3\tmain" \
+	"4\tptwrite2" \
+	]
+}
+
+# Test payload printing during stepping
+with_test_prefix "Stepping" {
+    gdb_test "record goto 10" "Can't go to an auxiliary instruction\."
+    gdb_test "record goto 9" ".*ptwrite.* at .*"
+    gdb_test "stepi" ".*\\\[0x42\\\].*"
+    gdb_test "reverse-stepi" ".*\\\[0x42\\\].*"
+    gdb_test "continue" [multi_line \
+	    ".*\\\[0x42\\\]" \
+	    "\\\[0x43\\\].*" \
+	    ]
+    gdb_test "reverse-continue" [multi_line \
+	    ".*\\\[0x43\\\]" \
+	    "\\\[0x42\\\].*" \
+	    ]
+}
+
+# Test auxiliary type in python
+gdb_test_multiline "auxiliary type in python" \
+    "python" "" \
+    "h = gdb.current_recording().instruction_history" "" \
+    "for insn in h:" "" \
+    "    if hasattr(insn, 'decoded'):" "" \
+    "        print(insn.decoded.decode())" "" \
+    "    elif hasattr(insn, 'data'):" "" \
+    "        print(insn.data)" "" \
+    "end" \
+    [multi_line \
+	".*mov    -0x4\\\(%(e|r)bp\\\),%(e|r)ax" \
+	"ptwrite %eax" \
+	"0x42" \
+	"nop.*" \
+	"mov    -0x4\\\(%(e|r)bp\\\),%(e|r)ax" \
+	"ptwrite %eax" \
+	"0x43" \
+	"nop.*"
+    ]
+
+
+### 2. Test filter registration
+### 2.1 Custom filter
+with_test_prefix "Custom" {
+    gdb_test_multiline "register filter in python" \
+	"python" "" \
+	"def my_filter(payload, ip):" "" \
+	"    if  payload == 66:" "" \
+	"        return \"payload: {0}, ip: {1:#x}\".format(payload, ip)" "" \
+	"    else:" "" \
+	"        return None" "" \
+	"def factory(thread): return my_filter" "" \
+	"import gdb.ptwrite" "" \
+	"gdb.ptwrite.register_filter_factory(factory)" "" \
+	"end" ""
+
+    gdb_test "record instruction-history 1" [multi_line \
+	".*\[0-9\]+\t   $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	"\[0-9\]+\t   \\\[payload: 66, ip: $hex\\\]" \
+	".*\[0-9\]+\t   $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	"\[0-9\]+\t   $hex <ptwrite2\\+\[0-9\]+>:.*" \
+	]
+}
+
+### 2.2 None as filter. This resets the default behaviour.
+with_test_prefix "None" {
+    gdb_test_multiline "register filter in python" \
+	"python" "" \
+	"import gdb.ptwrite" "" \
+	"gdb.ptwrite.register_filter_factory(None)" "" \
+	"end" ""
+
+    gdb_test "record instruction-history 1" [multi_line \
+	".*\[0-9\]+\t   $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	"\[0-9\]+\t   \\\[0x42\\\]" \
+	".*\[0-9\]+\t   $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	"\[0-9\]+\t   \\\[0x43\\\].*" \
+	]
+}
+
+### 2.3 Lambdas as filter
+with_test_prefix "Lambdas" {
+    gdb_test_multiline "register filter in python" \
+	"python" "" \
+	"import gdb.ptwrite" "" \
+	"lambda_filter = lambda payload, ip: \"{}\".format(payload + 2)" "" \
+	"gdb.ptwrite.register_filter_factory(lambda thread : lambda_filter)" "" \
+	"end" ""
+
+    gdb_test "record instruction-history 1" [multi_line \
+	".*\[0-9\]+\t   $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	"\[0-9\]+\t   \\\[68\\\]" \
+	".*\[0-9\]+\t   $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	"\[0-9\]+\t   \\\[69\\\].*" \
+	] "Lambdas: record instruction-history 1"
+}
+
+### 2.4 Functors as filter
+with_test_prefix "Functors" {
+    gdb_test_multiline "register filter in python" \
+	"python" "" \
+	"import gdb.ptwrite" "" \
+	"class foobar(object):" "" \
+	"    def __init__(self):" "" \
+	"        self.variable = 0" "" \
+	"    def __call__(self, payload, ip):" "" \
+	"        self.variable += 1" "" \
+	"        return \"{}, {}\".format(self.variable, payload)" "" \
+	"gdb.ptwrite.register_filter_factory(lambda thread : foobar())" "" \
+	"end" ""
+
+    gdb_test "record instruction-history 1" [multi_line \
+	".*\[0-9\]+\t   $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	"\[0-9\]+\t   \\\[1, 66\\\]" \
+	".*\[0-9\]+\t   $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+	"\[0-9\]+\t   \\\[2, 67\\\].*" \
+	] "Functors: record instruction-history 1"
+}
diff --git a/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S b/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S
new file mode 100644
index 00000000000..a0840995104
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S
@@ -0,0 +1,544 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+   This file has been generated using gcc version 10.3.1 20210422
+   (Red Hat 10.3.1-1):
+   gcc -S -dA -g -mptwrite ptwrite.c -o x86_64-ptwrite.S.  */
+
+	.file	"ptwrite.c"
+	.text
+.Ltext0:
+	.globl	ptwrite1
+	.type	ptwrite1, @function
+ptwrite1:
+.LFB4096:
+	.file 1 "ptwrite.c"
+	# ptwrite.c:22:1
+	.loc 1 22 1
+	.cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset 6, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register 6
+	movl	%edi, -20(%rbp)
+	# ptwrite.c:23:3
+	.loc 1 23 3
+	movl	-20(%rbp), %eax
+	movl	%eax, -4(%rbp)
+.LBB6:
+.LBB7:
+	.file 2 "/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h"
+	# /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3
+	.loc 2 307 3
+	movl	-4(%rbp), %eax
+	ptwrite	%eax
+	# /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1
+	.loc 2 308 1
+	nop
+.LBE7:
+.LBE6:
+	# ptwrite.c:24:1
+	.loc 1 24 1
+	nop
+	popq	%rbp
+	.cfi_def_cfa 7, 8
+# SUCC: EXIT [always]
+	ret
+	.cfi_endproc
+.LFE4096:
+	.size	ptwrite1, .-ptwrite1
+	.globl	ptwrite2
+	.type	ptwrite2, @function
+ptwrite2:
+.LFB4097:
+	# ptwrite.c:28:1
+	.loc 1 28 1
+	.cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset 6, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register 6
+	movl	%edi, -20(%rbp)
+	# ptwrite.c:29:3
+	.loc 1 29 3
+	movl	-20(%rbp), %eax
+	movl	%eax, -4(%rbp)
+.LBB8:
+.LBB9:
+	# /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:307:3
+	.loc 2 307 3
+	movl	-4(%rbp), %eax
+	ptwrite	%eax
+	# /usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h:308:1
+	.loc 2 308 1
+	nop
+.LBE9:
+.LBE8:
+	# ptwrite.c:30:1
+	.loc 1 30 1
+	nop
+	popq	%rbp
+	.cfi_def_cfa 7, 8
+# SUCC: EXIT [always]
+	ret
+	.cfi_endproc
+.LFE4097:
+	.size	ptwrite2, .-ptwrite2
+	.globl	main
+	.type	main, @function
+main:
+.LFB4098:
+	# ptwrite.c:34:1
+	.loc 1 34 1
+	.cfi_startproc
+# BLOCK 2 seq:0
+# PRED: ENTRY (FALLTHRU)
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset 6, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register 6
+	# ptwrite.c:35:3
+	.loc 1 35 3
+	movl	$66, %edi
+	call	ptwrite1
+	# ptwrite.c:36:3
+	.loc 1 36 3
+	movl	$67, %edi
+	call	ptwrite2
+	# ptwrite.c:38:10
+	.loc 1 38 10
+	movl	$0, %eax
+	# ptwrite.c:39:1
+	.loc 1 39 1
+	popq	%rbp
+	.cfi_def_cfa 7, 8
+# SUCC: EXIT [always]
+	ret
+	.cfi_endproc
+.LFE4098:
+	.size	main, .-main
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x159	# Length of Compilation Unit Info
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x8	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF15	# DW_AT_producer: "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -mptwrite -mtune=generic -march=x86-64 -g"
+	.byte	0xc	# DW_AT_language
+	.long	.LASF16	# DW_AT_name: "ptwrite.c"
+	.long	.LASF17	# DW_AT_comp_dir: "gdb/gdb/testsuite/gdb.btrace"
+	.quad	.Ltext0	# DW_AT_low_pc
+	.quad	.Letext0-.Ltext0	# DW_AT_high_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+	.uleb128 0x2	# (DIE (0x2d) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.ascii "int\0"	# DW_AT_name
+	.uleb128 0x3	# (DIE (0x34) DW_TAG_base_type)
+	.byte	0x2	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.long	.LASF0	# DW_AT_name: "short int"
+	.uleb128 0x3	# (DIE (0x3b) DW_TAG_base_type)
+	.byte	0x1	# DW_AT_byte_size
+	.byte	0x6	# DW_AT_encoding
+	.long	.LASF1	# DW_AT_name: "char"
+	.uleb128 0x3	# (DIE (0x42) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.long	.LASF2	# DW_AT_name: "long long int"
+	.uleb128 0x3	# (DIE (0x49) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x4	# DW_AT_encoding
+	.long	.LASF3	# DW_AT_name: "float"
+	.uleb128 0x3	# (DIE (0x50) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF4	# DW_AT_name: "long unsigned int"
+	.uleb128 0x3	# (DIE (0x57) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.long	.LASF5	# DW_AT_name: "long int"
+	.uleb128 0x3	# (DIE (0x5e) DW_TAG_base_type)
+	.byte	0x1	# DW_AT_byte_size
+	.byte	0x8	# DW_AT_encoding
+	.long	.LASF6	# DW_AT_name: "unsigned char"
+	.uleb128 0x3	# (DIE (0x65) DW_TAG_base_type)
+	.byte	0x2	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF7	# DW_AT_name: "short unsigned int"
+	.uleb128 0x3	# (DIE (0x6c) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF8	# DW_AT_name: "unsigned int"
+	.uleb128 0x3	# (DIE (0x73) DW_TAG_base_type)
+	.byte	0x1	# DW_AT_byte_size
+	.byte	0x6	# DW_AT_encoding
+	.long	.LASF9	# DW_AT_name: "signed char"
+	.uleb128 0x3	# (DIE (0x7a) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF10	# DW_AT_name: "long long unsigned int"
+	.uleb128 0x3	# (DIE (0x81) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x4	# DW_AT_encoding
+	.long	.LASF11	# DW_AT_name: "double"
+	.uleb128 0x4	# (DIE (0x88) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF18	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (ptwrite.c)
+	.byte	0x21	# DW_AT_decl_line
+	.byte	0x1	# DW_AT_decl_column
+			# DW_AT_prototyped
+	.long	0x2d	# DW_AT_type
+	.quad	.LFB4098	# DW_AT_low_pc
+	.quad	.LFE4098-.LFB4098	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_tail_call_sites
+	.uleb128 0x5	# (DIE (0xa6) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF12	# DW_AT_name: "ptwrite2"
+	.byte	0x1	# DW_AT_decl_file (ptwrite.c)
+	.byte	0x1b	# DW_AT_decl_line
+	.byte	0x1	# DW_AT_decl_column
+			# DW_AT_prototyped
+	.quad	.LFB4097	# DW_AT_low_pc
+	.quad	.LFE4097-.LFB4097	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+	.long	0xf5	# DW_AT_sibling
+	.uleb128 0x6	# (DIE (0xc4) DW_TAG_formal_parameter)
+	.long	.LASF14	# DW_AT_name: "value"
+	.byte	0x1	# DW_AT_decl_file (ptwrite.c)
+	.byte	0x1b	# DW_AT_decl_line
+	.byte	0xf	# DW_AT_decl_column
+	.long	0x2d	# DW_AT_type
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -36
+	.uleb128 0x7	# (DIE (0xd3) DW_TAG_inlined_subroutine)
+	.long	0x144	# DW_AT_abstract_origin
+	.quad	.LBB8	# DW_AT_low_pc
+	.quad	.LBE8-.LBB8	# DW_AT_high_pc
+	.byte	0x1	# DW_AT_call_file (ptwrite.c)
+	.byte	0x1d	# DW_AT_call_line
+	.byte	0x3	# DW_AT_call_column
+	.uleb128 0x8	# (DIE (0xeb) DW_TAG_formal_parameter)
+	.long	0x14e	# DW_AT_abstract_origin
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -20
+	.byte	0	# end of children of DIE 0xd3
+	.byte	0	# end of children of DIE 0xa6
+	.uleb128 0x5	# (DIE (0xf5) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF13	# DW_AT_name: "ptwrite1"
+	.byte	0x1	# DW_AT_decl_file (ptwrite.c)
+	.byte	0x15	# DW_AT_decl_line
+	.byte	0x1	# DW_AT_decl_column
+			# DW_AT_prototyped
+	.quad	.LFB4096	# DW_AT_low_pc
+	.quad	.LFE4096-.LFB4096	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+	.long	0x144	# DW_AT_sibling
+	.uleb128 0x6	# (DIE (0x113) DW_TAG_formal_parameter)
+	.long	.LASF14	# DW_AT_name: "value"
+	.byte	0x1	# DW_AT_decl_file (ptwrite.c)
+	.byte	0x15	# DW_AT_decl_line
+	.byte	0xf	# DW_AT_decl_column
+	.long	0x2d	# DW_AT_type
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -36
+	.uleb128 0x7	# (DIE (0x122) DW_TAG_inlined_subroutine)
+	.long	0x144	# DW_AT_abstract_origin
+	.quad	.LBB6	# DW_AT_low_pc
+	.quad	.LBE6-.LBB6	# DW_AT_high_pc
+	.byte	0x1	# DW_AT_call_file (ptwrite.c)
+	.byte	0x17	# DW_AT_call_line
+	.byte	0x3	# DW_AT_call_column
+	.uleb128 0x8	# (DIE (0x13a) DW_TAG_formal_parameter)
+	.long	0x14e	# DW_AT_abstract_origin
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -20
+	.byte	0	# end of children of DIE 0x122
+	.byte	0	# end of children of DIE 0xf5
+	.uleb128 0x9	# (DIE (0x144) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF19	# DW_AT_name: "_ptwrite32"
+	.byte	0x2	# DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h)
+	.value	0x131	# DW_AT_decl_line
+	.byte	0x1	# DW_AT_decl_column
+			# DW_AT_prototyped
+	.byte	0x3	# DW_AT_inline
+			# DW_AT_artificial
+	.uleb128 0xa	# (DIE (0x14e) DW_TAG_formal_parameter)
+	.ascii "__B\0"	# DW_AT_name
+	.byte	0x2	# DW_AT_decl_file (/usr/lib/gcc/x86_64-redhat-linux/10/include/immintrin.h)
+	.value	0x131	# DW_AT_decl_line
+	.byte	0x16	# DW_AT_decl_column
+	.long	0x6c	# DW_AT_type
+	.byte	0	# end of children of DIE 0x144
+	.byte	0	# end of children of DIE 0xb
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	# (abbrev code)
+	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x25	# (DW_AT_producer)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x13	# (DW_AT_language)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x1b	# (DW_AT_comp_dir)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x10	# (DW_AT_stmt_list)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0	# DW_children_no
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x39	# (DW_AT_decl_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x27	# (DW_AT_prototyped)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2116	# (DW_AT_GNU_all_tail_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x39	# (DW_AT_decl_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x27	# (DW_AT_prototyped)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x39	# (DW_AT_decl_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	# (abbrev code)
+	.uleb128 0x1d	# (TAG: DW_TAG_inlined_subroutine)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x58	# (DW_AT_call_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x59	# (DW_AT_call_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x57	# (DW_AT_call_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0x5	# (DW_FORM_data2)
+	.uleb128 0x39	# (DW_AT_decl_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x27	# (DW_AT_prototyped)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x20	# (DW_AT_inline)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x34	# (DW_AT_artificial)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0xa	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0x5	# (DW_FORM_data2)
+	.uleb128 0x39	# (DW_AT_decl_column)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c	# Length of Address Ranges Info
+	.value	0x2	# DWARF aranges version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x8	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 16 byte boundary
+	.value	0
+	.quad	.Ltext0	# Address
+	.quad	.Letext0-.Ltext0	# Length
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF2:
+	.string	"long long int"
+.LASF14:
+	.string	"value"
+.LASF19:
+	.string	"_ptwrite32"
+.LASF8:
+	.string	"unsigned int"
+.LASF17:
+	.string	"gdb/gdb/testsuite/gdb.btrace"
+.LASF18:
+	.string	"main"
+.LASF16:
+	.string	"ptwrite.c"
+.LASF4:
+	.string	"long unsigned int"
+.LASF10:
+	.string	"long long unsigned int"
+.LASF15:
+	.string	"GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -mptwrite -mtune=generic -march=x86-64 -g"
+.LASF13:
+	.string	"ptwrite1"
+.LASF12:
+	.string	"ptwrite2"
+.LASF6:
+	.string	"unsigned char"
+.LASF1:
+	.string	"char"
+.LASF5:
+	.string	"long int"
+.LASF11:
+	.string	"double"
+.LASF7:
+	.string	"short unsigned int"
+.LASF9:
+	.string	"signed char"
+.LASF3:
+	.string	"float"
+.LASF0:
+	.string	"short int"
+	.ident	"GCC: (GNU) 10.3.1 20210422 (Red Hat 10.3.1-1)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index b4900ae25a6..79509e96ce2 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -4044,6 +4044,78 @@ gdb_caching_proc allow_btrace_pt_tests {} {
     return $allow_btrace_pt_tests
 }
 
+# Run a test on the target to see if it supports ptwrite instructions and
+# if GDB can decode ptwrite events.  Return 1 if so, 0 if it does not.
+
+gdb_caching_proc allow_btrace_ptw_tests {} {
+    global srcdir subdir gdb_prompt inferior_exited_re decimal
+
+    require allow_btrace_pt_tests
+    set me "allow_btrace_ptw_tests"
+
+    set src {
+	int
+	main ()
+	{
+	  asm volatile ("PTWRITE %0;" : : "b"(0x42));
+	  return 0;
+	}
+    }
+
+    if {![gdb_simple_compile $me $src executable]} {
+	return 1
+    }
+
+    gdb_exit
+    gdb_start
+    gdb_reinitialize_dir $srcdir/$subdir
+    gdb_load "$obj"
+    if ![runto_main] {
+	return 1
+    }
+
+    gdb_test_no_output "record btrace pt" "$me: record btrace pt"
+
+    set allow_btrace_ptw_tests 2
+    gdb_test_multiple "next" "$me: next" {
+	-re -wrap ".*Illegal instruction.*" {
+	    verbose -log "$me:  ptwrite instruction support not detected."
+	    set allow_btrace_ptw_tests 0
+	}
+	-re -wrap ".*$inferior_exited_re normally.*" {
+	    verbose -log "$me:  ptwrite support not detected."
+	    set allow_btrace_ptw_tests 0
+	}
+	-re -wrap "$decimal.*(at|in|return 0).*" {
+	    set allow_btrace_ptw_tests 1
+	}
+    }
+
+    if { $allow_btrace_ptw_tests == 1 } {
+	# Show the func-call-history to get the packet trace.
+	gdb_test "record function-call-history" ".*"
+
+	gdb_test_multiple "maintenance btrace packet-history 0,1000" \
+	    "$me: check decoding support" {
+	    -re  "ptw" {
+		verbose -log "$me:  ptwrite decoding support detected."
+		set allow_btrace_ptw_tests 1
+	    }
+	    -re ".*${gdb_prompt} $" {
+		verbose -log "$me:  ptwrite decoding support not detected."
+		set allow_btrace_ptw_tests 0
+	    }
+	}
+    }
+
+    gdb_exit
+    remote_file build delete $obj
+
+    verbose "$me:  returning $allow_btrace_ptw_tests" 2
+    return $allow_btrace_ptw_tests
+}
+
+
 # Run a test on the target to see if it supports Aarch64 SVE hardware.
 # Return 1 if so, 0 if it does not.  Note this causes a restart of GDB.
 
diff --git a/gdbsupport/common.m4 b/gdbsupport/common.m4
index 3909ec81ccb..1ad2395e80f 100644
--- a/gdbsupport/common.m4
+++ b/gdbsupport/common.m4
@@ -190,6 +190,8 @@ AC_DEFUN([GDB_AC_COMMON], [
       AC_CHECK_FUNCS(pt_insn_event)
       AC_CHECK_MEMBERS([struct pt_insn.enabled, struct pt_insn.resynced], [], [],
 		       [#include <intel-pt.h>])
+      AC_CHECK_MEMBERS([struct pt_event.variant.ptwrite], [], [],
+		       [#include <intel-pt.h>])
       LIBS=$save_LIBS
     fi
   fi
diff --git a/gdbsupport/config.in b/gdbsupport/config.in
index 2cdc1fbde61..8ce8e23bc24 100644
--- a/gdbsupport/config.in
+++ b/gdbsupport/config.in
@@ -238,6 +238,9 @@
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
+/* Define to 1 if `variant.ptwrite' is a member of `struct pt_event'. */
+#undef HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE
+
 /* Define to 1 if `enabled' is a member of `struct pt_insn'. */
 #undef HAVE_STRUCT_PT_INSN_ENABLED
 
diff --git a/gdbsupport/configure b/gdbsupport/configure
index 9433ac41468..7a10c96bd75 100755
--- a/gdbsupport/configure
+++ b/gdbsupport/configure
@@ -9625,6 +9625,17 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+fi
+
+      ac_fn_c_check_member "$LINENO" "struct pt_event" "variant.ptwrite" "ac_cv_member_struct_pt_event_variant_ptwrite" "#include <intel-pt.h>
+"
+if test "x$ac_cv_member_struct_pt_event_variant_ptwrite" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE 1
+_ACEOF
+
+
 fi
 
       LIBS=$save_LIBS
-- 
2.34.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 01/10] btrace: Introduce auxiliary instructions.
  2023-07-04 12:35 ` [PATCH v9 01/10] btrace: Introduce auxiliary instructions Felix Willgerodt
@ 2023-07-04 12:44   ` Eli Zaretskii
  0 siblings, 0 replies; 33+ messages in thread
From: Eli Zaretskii @ 2023-07-04 12:44 UTC (permalink / raw)
  To: Felix Willgerodt; +Cc: gdb-patches, markus.t.metzger, simark

> Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> Date: Tue,  4 Jul 2023 14:35:51 +0200
> From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> 
> Auxiliary instructions are pseudo instructions pointing to auxiliary data.
> This auxiliary data can be printed in all commands displaying (record
> function-call-history, record instruction-history) or stepping through
> (stepi etc.) the execution history, which will be introduced in the next
> commits.
> 
> This patch is in preparation for the new ptwrite feature, which is based on
> auxiliary instructions.
> ---
>  gdb/btrace.c        |  2 ++
>  gdb/btrace.h        | 24 +++++++++++++++++++++---
>  gdb/doc/gdb.texinfo |  3 +++
>  3 files changed, 26 insertions(+), 3 deletions(-)

OK for the gdb.texinfo part, thanks.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 02/10] btrace: Enable auxiliary instructions in record instruction-history.
  2023-07-04 12:35 ` [PATCH v9 02/10] btrace: Enable auxiliary instructions in record instruction-history Felix Willgerodt
@ 2023-07-04 12:45   ` Eli Zaretskii
  0 siblings, 0 replies; 33+ messages in thread
From: Eli Zaretskii @ 2023-07-04 12:45 UTC (permalink / raw)
  To: Felix Willgerodt; +Cc: gdb-patches, markus.t.metzger, simark

> Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> Date: Tue,  4 Jul 2023 14:35:52 +0200
> From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> 
> Print the auxiliary data when a btrace_insn of type BTRACE_INSN_AUX
> is encountered in the instruction-history.  Printing is active by default,
> it can be silenced with the /a modifier.
> 
> This patch is in preparation for the new ptwrite feature, which is based on
> auxiliary instructions.
> ---
>  gdb/disasm-flags.h  |  1 +
>  gdb/doc/gdb.texinfo |  3 +++
>  gdb/record-btrace.c | 14 ++++++++++++++
>  gdb/record.c        |  5 +++++
>  4 files changed, 23 insertions(+)

The gdb.texinfo part is OK, thanks.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 06/10] python: Add clear() to gdb.Record.
  2023-07-04 12:35 ` [PATCH v9 06/10] python: Add clear() to gdb.Record Felix Willgerodt
@ 2023-07-04 12:46   ` Eli Zaretskii
  2023-07-05 10:03     ` Willgerodt, Felix
  2023-07-06 16:11   ` Tom Tromey
  1 sibling, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2023-07-04 12:46 UTC (permalink / raw)
  To: Felix Willgerodt; +Cc: gdb-patches, markus.t.metzger, simark

> Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> Date: Tue,  4 Jul 2023 14:35:56 +0200
> From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> 
> This function allows to clear the trace data from python, forcing to
> re-decode the trace for successive commands.
> This will be used in future ptwrite patches, to trigger re-decoding when
> the ptwrite filter changes.
> ---
>  gdb/doc/python.texi                           |  5 +++++
>  gdb/python/py-record-btrace.c                 | 13 +++++++++++++
>  gdb/python/py-record-btrace.h                 |  3 +++
>  gdb/python/py-record.c                        | 16 ++++++++++++++++
>  gdb/testsuite/gdb.python/py-record-btrace.exp |  4 ++++
>  5 files changed, 41 insertions(+)

The documentation part is OK, thanks.

Is this addition NEWS-worthy?

Reviewed-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 03/10] btrace: Enable auxiliary instructions in record function-call-history.
  2023-07-04 12:35 ` [PATCH v9 03/10] btrace: Enable auxiliary instructions in record function-call-history Felix Willgerodt
@ 2023-07-04 12:47   ` Eli Zaretskii
  0 siblings, 0 replies; 33+ messages in thread
From: Eli Zaretskii @ 2023-07-04 12:47 UTC (permalink / raw)
  To: Felix Willgerodt; +Cc: gdb-patches, markus.t.metzger, simark

> Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> Date: Tue,  4 Jul 2023 14:35:53 +0200
> From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> 
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 5f15875f5dd..55a51449c7a 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -8134,8 +8134,9 @@ that function, the source lines for this instruction sequence (if the
>  @code{/l} modifier is specified), and the instructions numbers that form
>  the sequence (if the @code{/i} modifier is specified).  The function names
>  are indented to reflect the call stack depth if the @code{/c} modifier is
> -specified.  The @code{/l}, @code{/i}, and @code{/c} modifiers can be given
> -together.
> +specified.  Printing auxiliary information is enabled by default and can be
> +omitted with the @code{/a} modifier.  The @code{/l}, @code{/i}, @code{/a},
> +and @code{/c} modifiers can be given together.
>  
>  @smallexample
>  (@value{GDBP}) @b{list 1, 10}

This part is OK, thanks.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 07/10] btrace, gdbserver: Add ptwrite to btrace_config_pt.
  2023-07-04 12:35 ` [PATCH v9 07/10] btrace, gdbserver: Add ptwrite to btrace_config_pt Felix Willgerodt
@ 2023-07-04 12:49   ` Eli Zaretskii
  2023-07-05 10:04     ` Willgerodt, Felix
  0 siblings, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2023-07-04 12:49 UTC (permalink / raw)
  To: Felix Willgerodt; +Cc: gdb-patches, markus.t.metzger, simark

> Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> Date: Tue,  4 Jul 2023 14:35:57 +0200
> From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> 
> This enables gdb and gdbserver to communicate about ptwrite support.  If
> ptwrite support would be enabled unconditionally, GDBs with older libipt
> versions would break.
> ---
>  gdb/btrace.c                 |  8 +++++++-
>  gdb/doc/gdb.texinfo          | 21 +++++++++++++++++++++
>  gdb/features/btrace-conf.dtd |  1 +
>  gdb/remote.c                 | 33 +++++++++++++++++++++++++++++++++
>  gdbserver/linux-low.cc       |  3 +++
>  gdbserver/server.cc          | 18 ++++++++++++++++++
>  gdbsupport/btrace-common.h   |  6 ++++++
>  7 files changed, 89 insertions(+), 1 deletion(-)

Thanks.

> +@item Qbtrace-conf:pt:ptwrite=@var{(yes|no)}
> +Indicate support for @code{PTWRITE} packets.  This allows for backwards
> +compatibility.

is it intentional that PTWRITE is in caps here?  In other places you
used lower-case.

> +Reply:
> +@table @samp
> +@item OK
> +The ptwrite config parameter has been set.

"Config parameter"?  Isn't this the response to the ptwrite packet?

Reviewed-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 05/10] python: Introduce gdb.RecordAuxiliary class.
  2023-07-04 12:35 ` [PATCH v9 05/10] python: Introduce gdb.RecordAuxiliary class Felix Willgerodt
@ 2023-07-04 12:52   ` Eli Zaretskii
  2023-07-05 10:04     ` Willgerodt, Felix
  0 siblings, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2023-07-04 12:52 UTC (permalink / raw)
  To: Felix Willgerodt; +Cc: gdb-patches, markus.t.metzger, simark

> Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> Date: Tue,  4 Jul 2023 14:35:55 +0200
> From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> 
> Auxiliary instructions are no real instructions and get their own object
> class, similar to gaps. gdb.Record.instruction_history is now possibly a
> list of gdb.RecordInstruction, gdb.RecordGap or gdb.RecordAuxiliary
> objects.
> 
> This patch is in preparation for the new ptwrite feature, which is based on
> auxiliary instructions.
> ---
>  gdb/doc/python.texi           | 13 ++++++
>  gdb/python/py-record-btrace.c | 81 +++++++++++++++++++++++++++++------
>  gdb/python/py-record-btrace.h |  3 ++
>  gdb/python/py-record.c        | 62 +++++++++++++++++++++++++--
>  gdb/python/py-record.h        |  7 +++
>  5 files changed, 150 insertions(+), 16 deletions(-)

Thanks.

> +@defvar RecordAuxiliary.number
> +An integer identifying this auxiliary.  @code{number} corresponds to the numbers
> +seen in @code{record instruction-history} (@pxref{Process Record and Replay}).

I think "number" should be in @var, like this:

 +@defvar RecordAuxiliary.@var{number}
 +An integer identifying this auxiliary.  @var{number} corresponds to the numbers
 +seen in @code{record instruction-history} (@pxref{Process Record and Replay}).

because "number" is not a literal string, it stands for some numerical
string.  Right?

Reviewed-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 10/10] btrace: Extend ptwrite event decoding.
  2023-07-04 12:36 ` [PATCH v9 10/10] btrace: Extend ptwrite event decoding Felix Willgerodt
@ 2023-07-04 12:56   ` Eli Zaretskii
  2023-07-05 10:04     ` Willgerodt, Felix
  2023-07-06 16:46   ` Tom Tromey
  1 sibling, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2023-07-04 12:56 UTC (permalink / raw)
  To: Felix Willgerodt; +Cc: gdb-patches, markus.t.metzger, simark

> Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> Date: Tue,  4 Jul 2023 14:36:00 +0200
> From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> 
> Call the ptwrite filter function whenever a ptwrite event is decoded.
> The returned string is written to the aux_data string table and a
> corresponding auxiliary instruction is appended to the function segment.
> ---
>  gdb/NEWS                                  |   7 +
>  gdb/btrace.c                              |  58 +++
>  gdb/config.in                             |   3 +
>  gdb/configure                             |  11 +
>  gdb/doc/python.texi                       | 148 ++++++
>  gdb/testsuite/gdb.btrace/i386-ptwrite.S   | 550 ++++++++++++++++++++++
>  gdb/testsuite/gdb.btrace/ptwrite.c        |  39 ++
>  gdb/testsuite/gdb.btrace/ptwrite.exp      | 202 ++++++++
>  gdb/testsuite/gdb.btrace/x86_64-ptwrite.S | 544 +++++++++++++++++++++
>  gdb/testsuite/lib/gdb.exp                 |  72 +++
>  gdbsupport/common.m4                      |   2 +
>  gdbsupport/config.in                      |   3 +
>  gdbsupport/configure                      |  11 +
>  13 files changed, 1650 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.btrace/i386-ptwrite.S
>  create mode 100644 gdb/testsuite/gdb.btrace/ptwrite.c
>  create mode 100644 gdb/testsuite/gdb.btrace/ptwrite.exp
>  create mode 100644 gdb/testsuite/gdb.btrace/x86_64-ptwrite.S

Thanks, the documentation parts are OK, with this one nit:

> +The @code{gdb.ptwrite} module allows customizing the default output of
> +@code{PTWRITE} auxiliary information.  A custom Python function can be
> +registered as the @code{PTWRITE} filter function.  This function will be
> +called with the @code{PTWRITE} payload and PC as arguments during trace
> +decoding.  It can return a string, which will be printed by @value{GDBN}
> +during the aforementioned commands, or @code{None}, resulting in no output.
> +To register such a filter function, the user needs to provide a filter factory
> +function, which returns a new filter function object to be called by GDB.
                                                                        ^^^
"@value{GDBN}"

Reviewed-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v9 06/10] python: Add clear() to gdb.Record.
  2023-07-04 12:46   ` Eli Zaretskii
@ 2023-07-05 10:03     ` Willgerodt, Felix
  2023-07-05 11:35       ` Eli Zaretskii
  0 siblings, 1 reply; 33+ messages in thread
From: Willgerodt, Felix @ 2023-07-05 10:03 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, Metzger, Markus T, simark

> -----Original Message-----
> From: Eli Zaretskii <eliz@gnu.org>
> Sent: Dienstag, 4. Juli 2023 14:46
> To: Willgerodt, Felix <felix.willgerodt@intel.com>
> Cc: gdb-patches@sourceware.org; Metzger, Markus T
> <markus.t.metzger@intel.com>; simark@simark.ca
> Subject: Re: [PATCH v9 06/10] python: Add clear() to gdb.Record.
> 
> > Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> > Date: Tue,  4 Jul 2023 14:35:56 +0200
> > From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> >
> > This function allows to clear the trace data from python, forcing to
> > re-decode the trace for successive commands.
> > This will be used in future ptwrite patches, to trigger re-decoding when
> > the ptwrite filter changes.
> > ---
> >  gdb/doc/python.texi                           |  5 +++++
> >  gdb/python/py-record-btrace.c                 | 13 +++++++++++++
> >  gdb/python/py-record-btrace.h                 |  3 +++
> >  gdb/python/py-record.c                        | 16 ++++++++++++++++
> >  gdb/testsuite/gdb.python/py-record-btrace.exp |  4 ++++
> >  5 files changed, 41 insertions(+)
> 
> The documentation part is OK, thanks.
> 
> Is this addition NEWS-worthy?
> 
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>

Thanks! Good question, I so far decided no, as it isn't really a big feature.
Not sure, if it is GDB policy to mention every new command, I can for sure
add a mention if you think it make sense.

Felix
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v9 07/10] btrace, gdbserver: Add ptwrite to btrace_config_pt.
  2023-07-04 12:49   ` Eli Zaretskii
@ 2023-07-05 10:04     ` Willgerodt, Felix
  0 siblings, 0 replies; 33+ messages in thread
From: Willgerodt, Felix @ 2023-07-05 10:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, Metzger, Markus T, simark

> -----Original Message-----
> From: Eli Zaretskii <eliz@gnu.org>
> Sent: Dienstag, 4. Juli 2023 14:50
> To: Willgerodt, Felix <felix.willgerodt@intel.com>
> Cc: gdb-patches@sourceware.org; Metzger, Markus T
> <markus.t.metzger@intel.com>; simark@simark.ca
> Subject: Re: [PATCH v9 07/10] btrace, gdbserver: Add ptwrite to
> btrace_config_pt.
> 
> > Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> > Date: Tue,  4 Jul 2023 14:35:57 +0200
> > From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> >
> > This enables gdb and gdbserver to communicate about ptwrite support.  If
> > ptwrite support would be enabled unconditionally, GDBs with older libipt
> > versions would break.
> > ---
> >  gdb/btrace.c                 |  8 +++++++-
> >  gdb/doc/gdb.texinfo          | 21 +++++++++++++++++++++
> >  gdb/features/btrace-conf.dtd |  1 +
> >  gdb/remote.c                 | 33 +++++++++++++++++++++++++++++++++
> >  gdbserver/linux-low.cc       |  3 +++
> >  gdbserver/server.cc          | 18 ++++++++++++++++++
> >  gdbsupport/btrace-common.h   |  6 ++++++
> >  7 files changed, 89 insertions(+), 1 deletion(-)
> 
> Thanks.
> 
> > +@item Qbtrace-conf:pt:ptwrite=@var{(yes|no)}
> > +Indicate support for @code{PTWRITE} packets.  This allows for backwards
> > +compatibility.
> 
> is it intentional that PTWRITE is in caps here?  In other places you
> used lower-case.

In this series, ptwrite has a couple of different meanings really.
First, it is an x86 instruction, these are usually written in caps, I actually
added the "@code" based on your previous feedback.

Then, ptwrite is also kind of the feature name. That is why different
implementation details, like the gdb.ptwrite python module, or the
ptwrite config parameter are named the same.

In the sentence that you commented on here, it is meant to mean
the ptwrite libipt paket. In that case, I would think ptwrite is again more
the instruction name, hence I wrote it in all caps.

I can only see ptwrite in lower letters in one place really:

+The ptwrite config parameter has been set.

I assume this is the occasion you meant? As it is specifically the RSP config
parameter mentioned here, and that is lower-case, I also put it lower case.

> > +Reply:
> > +@table @samp
> > +@item OK
> > +The ptwrite config parameter has been set.
> 
> "Config parameter"?  Isn't this the response to the ptwrite packet?
> 
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>

Thanks,
Felix
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v9 05/10] python: Introduce gdb.RecordAuxiliary class.
  2023-07-04 12:52   ` Eli Zaretskii
@ 2023-07-05 10:04     ` Willgerodt, Felix
  2023-07-05 11:37       ` Eli Zaretskii
  0 siblings, 1 reply; 33+ messages in thread
From: Willgerodt, Felix @ 2023-07-05 10:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, Metzger, Markus T, simark

> -----Original Message-----
> From: Eli Zaretskii <eliz@gnu.org>
> Sent: Dienstag, 4. Juli 2023 14:52
> To: Willgerodt, Felix <felix.willgerodt@intel.com>
> Cc: gdb-patches@sourceware.org; Metzger, Markus T
> <markus.t.metzger@intel.com>; simark@simark.ca
> Subject: Re: [PATCH v9 05/10] python: Introduce gdb.RecordAuxiliary class.
> 
> > Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> > Date: Tue,  4 Jul 2023 14:35:55 +0200
> > From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> >
> > Auxiliary instructions are no real instructions and get their own object
> > class, similar to gaps. gdb.Record.instruction_history is now possibly a
> > list of gdb.RecordInstruction, gdb.RecordGap or gdb.RecordAuxiliary
> > objects.
> >
> > This patch is in preparation for the new ptwrite feature, which is based on
> > auxiliary instructions.
> > ---
> >  gdb/doc/python.texi           | 13 ++++++
> >  gdb/python/py-record-btrace.c | 81
> +++++++++++++++++++++++++++++------
> >  gdb/python/py-record-btrace.h |  3 ++
> >  gdb/python/py-record.c        | 62 +++++++++++++++++++++++++--
> >  gdb/python/py-record.h        |  7 +++
> >  5 files changed, 150 insertions(+), 16 deletions(-)
> 
> Thanks.
> 
> > +@defvar RecordAuxiliary.number
> > +An integer identifying this auxiliary.  @code{number} corresponds to the
> numbers
> > +seen in @code{record instruction-history} (@pxref{Process Record and
> Replay}).
> 
> I think "number" should be in @var, like this:
> 
>  +@defvar RecordAuxiliary.@var{number}
>  +An integer identifying this auxiliary.  @var{number} corresponds to the
> numbers
>  +seen in @code{record instruction-history} (@pxref{Process Record and
> Replay}).
> 
> because "number" is not a literal string, it stands for some numerical
> string.  Right?

I just copied it from the RecordGap.number text to be honest, there it is
also in a @code. It is supposed to be the actual python member.
It is both code and a variable ;)
The surrounding test seems to favour code. I am happy to change it to
whatever you think is right. I see both equally possible.

> Reviewed-By: Eli Zaretskii <eliz@gnu.org>

Thanks!
Felix
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v9 10/10] btrace: Extend ptwrite event decoding.
  2023-07-04 12:56   ` Eli Zaretskii
@ 2023-07-05 10:04     ` Willgerodt, Felix
  0 siblings, 0 replies; 33+ messages in thread
From: Willgerodt, Felix @ 2023-07-05 10:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, Metzger, Markus T, simark

> -----Original Message-----
> From: Eli Zaretskii <eliz@gnu.org>
> Sent: Dienstag, 4. Juli 2023 14:57
> To: Willgerodt, Felix <felix.willgerodt@intel.com>
> Cc: gdb-patches@sourceware.org; Metzger, Markus T
> <markus.t.metzger@intel.com>; simark@simark.ca
> Subject: Re: [PATCH v9 10/10] btrace: Extend ptwrite event decoding.
> 
> > Cc: Felix Willgerodt <felix.willgerodt@intel.com>
> > Date: Tue,  4 Jul 2023 14:36:00 +0200
> > From: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> >
> > Call the ptwrite filter function whenever a ptwrite event is decoded.
> > The returned string is written to the aux_data string table and a
> > corresponding auxiliary instruction is appended to the function segment.
> > ---
> >  gdb/NEWS                                  |   7 +
> >  gdb/btrace.c                              |  58 +++
> >  gdb/config.in                             |   3 +
> >  gdb/configure                             |  11 +
> >  gdb/doc/python.texi                       | 148 ++++++
> >  gdb/testsuite/gdb.btrace/i386-ptwrite.S   | 550
> ++++++++++++++++++++++
> >  gdb/testsuite/gdb.btrace/ptwrite.c        |  39 ++
> >  gdb/testsuite/gdb.btrace/ptwrite.exp      | 202 ++++++++
> >  gdb/testsuite/gdb.btrace/x86_64-ptwrite.S | 544
> +++++++++++++++++++++
> >  gdb/testsuite/lib/gdb.exp                 |  72 +++
> >  gdbsupport/common.m4                      |   2 +
> >  gdbsupport/config.in                      |   3 +
> >  gdbsupport/configure                      |  11 +
> >  13 files changed, 1650 insertions(+)
> >  create mode 100644 gdb/testsuite/gdb.btrace/i386-ptwrite.S
> >  create mode 100644 gdb/testsuite/gdb.btrace/ptwrite.c
> >  create mode 100644 gdb/testsuite/gdb.btrace/ptwrite.exp
> >  create mode 100644 gdb/testsuite/gdb.btrace/x86_64-ptwrite.S
> 
> Thanks, the documentation parts are OK, with this one nit:
> 
> > +The @code{gdb.ptwrite} module allows customizing the default output of
> > +@code{PTWRITE} auxiliary information.  A custom Python function can be
> > +registered as the @code{PTWRITE} filter function.  This function will be
> > +called with the @code{PTWRITE} payload and PC as arguments during trace
> > +decoding.  It can return a string, which will be printed by @value{GDBN}
> > +during the aforementioned commands, or @code{None}, resulting in no
> output.
> > +To register such a filter function, the user needs to provide a filter factory
> > +function, which returns a new filter function object to be called by GDB.
>                                                                         ^^^
> "@value{GDBN}"
> 
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>

Thanks, I fixed the nit locally.

And thanks for the other reviews approvals.

Felix
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 06/10] python: Add clear() to gdb.Record.
  2023-07-05 10:03     ` Willgerodt, Felix
@ 2023-07-05 11:35       ` Eli Zaretskii
  0 siblings, 0 replies; 33+ messages in thread
From: Eli Zaretskii @ 2023-07-05 11:35 UTC (permalink / raw)
  To: Willgerodt, Felix; +Cc: gdb-patches, markus.t.metzger, simark

> From: "Willgerodt, Felix" <felix.willgerodt@intel.com>
> CC: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>, "Metzger,
>  Markus T" <markus.t.metzger@intel.com>, "simark@simark.ca" <simark@simark.ca>
> Date: Wed, 5 Jul 2023 10:03:11 +0000
> 
> > Is this addition NEWS-worthy?

> > 
> > Reviewed-By: Eli Zaretskii <eliz@gnu.org>
> 
> Thanks! Good question, I so far decided no, as it isn't really a big feature.
> Not sure, if it is GDB policy to mention every new command, I can for sure
> add a mention if you think it make sense.

Yes, I think we mention every new command in NEWS.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 05/10] python: Introduce gdb.RecordAuxiliary class.
  2023-07-05 10:04     ` Willgerodt, Felix
@ 2023-07-05 11:37       ` Eli Zaretskii
  0 siblings, 0 replies; 33+ messages in thread
From: Eli Zaretskii @ 2023-07-05 11:37 UTC (permalink / raw)
  To: Willgerodt, Felix; +Cc: gdb-patches, markus.t.metzger, simark

> From: "Willgerodt, Felix" <felix.willgerodt@intel.com>
> CC: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>, "Metzger,
>  Markus T" <markus.t.metzger@intel.com>, "simark@simark.ca" <simark@simark.ca>
> Date: Wed, 5 Jul 2023 10:04:53 +0000
> 
> > I think "number" should be in @var, like this:
> > 
> >  +@defvar RecordAuxiliary.@var{number}
> >  +An integer identifying this auxiliary.  @var{number} corresponds to the
> > numbers
> >  +seen in @code{record instruction-history} (@pxref{Process Record and
> > Replay}).
> > 
> > because "number" is not a literal string, it stands for some numerical
> > string.  Right?
> 
> I just copied it from the RecordGap.number text to be honest, there it is
> also in a @code. It is supposed to be the actual python member.
> It is both code and a variable ;)
> The surrounding test seems to favour code. I am happy to change it to
> whatever you think is right. I see both equally possible.

Yes, @var is the right markup here.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 06/10] python: Add clear() to gdb.Record.
  2023-07-04 12:35 ` [PATCH v9 06/10] python: Add clear() to gdb.Record Felix Willgerodt
  2023-07-04 12:46   ` Eli Zaretskii
@ 2023-07-06 16:11   ` Tom Tromey
  2023-07-13 12:34     ` Willgerodt, Felix
  1 sibling, 1 reply; 33+ messages in thread
From: Tom Tromey @ 2023-07-06 16:11 UTC (permalink / raw)
  To: Felix Willgerodt via Gdb-patches
  Cc: markus.t.metzger, simark, Felix Willgerodt

>>>>> Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org> writes:

> This function allows to clear the trace data from python, forcing to
> re-decode the trace for successive commands.
> This will be used in future ptwrite patches, to trigger re-decoding when
> the ptwrite filter changes.

> +PyObject *
> +recpy_bt_clear (PyObject *self, PyObject *args)
> +{
> +  const recpy_record_object * const record = (recpy_record_object *) self;
> +  thread_info *const tinfo = record->thread;

Normally in the Python layer, some care must be taken to ensure that
something sensible happens when a Python object outlives some underlying
gdb object.  That is why some types have an 'is_valid' method and why
there are the various *_REQUIRE_VALID macros.

It isn't a problem with this patch per se but it seems to me that this
code does not handle this situation properly.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 09/10] btrace, python: Enable ptwrite filter registration.
  2023-07-04 12:35 ` [PATCH v9 09/10] btrace, python: Enable ptwrite filter registration Felix Willgerodt
@ 2023-07-06 16:31   ` Tom Tromey
  2023-07-13 12:34     ` Willgerodt, Felix
  0 siblings, 1 reply; 33+ messages in thread
From: Tom Tromey @ 2023-07-06 16:31 UTC (permalink / raw)
  To: Felix Willgerodt via Gdb-patches
  Cc: markus.t.metzger, simark, Felix Willgerodt

>>>>> Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org> writes:

> By default GDB will be printing the hex payload of the ptwrite package as
> auxiliary information.  To customize this, the user can register a ptwrite
> filter function in python, that takes the payload and the PC as arguments and
> returns a string which will be printed instead.  Registering the filter
> function is done using a factory pattern to make per-thread filtering easier.

Thank you for the patch.

> +  /* Function pointer to the ptwrite callback.  Returns the string returned
> +     by the ptwrite filter function.  */
> +  gdb::optional<std::string> (*ptw_callback_fun) (const uint64_t payload,
> +						  const uint64_t ip,
> +						  const void *ptw_context)
> +						    = nullptr;
> +
> +  /* Context for the ptw_callback_fun.  */
> +  void *ptw_context = nullptr;

I tend to think it's better to use std::function here, rather than the
C-style pointer-and-data approach.

> diff --git a/gdb/python/lib/gdb/ptwrite.py b/gdb/python/lib/gdb/ptwrite.py

I gather the new stuff is documented in the next patch.

> +# _ptwrite_filter contains the per thread copies of the filter function.
> +# The keys are tuples of inferior id and thread id.
> +# The filter functions are created for each thread by calling the
> +# _ptwrite_filter_factory.
> +_ptwrite_filter = {}

It seems like when an inferior or thread is destroyed, the entries
should be removed from this map.

> +  gdbpy_ref<> py_payload (PyLong_FromUnsignedLongLong (payload));
> +  gdbpy_ref<> py_ip (PyLong_FromUnsignedLongLong (ip));

Both of these calls require null checks.

> +  gdbpy_ref<> py_result (PyObject_CallFunctionObjArgs ((PyObject *) ptw_filter,
> +							py_payload.get (),
> +							py_ip.get (),
> +							nullptr));
> +
> +  if (PyErr_Occurred ())

It's more idiomatic to check == nullptr than PyErr_Occurred.

> +  result = gdbpy_obj_to_string (py_result.get ()).get ();
> +
> +  if (PyErr_Occurred ())

Here too.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 00/10] Extensions for PTWRITE
  2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
                   ` (9 preceding siblings ...)
  2023-07-04 12:36 ` [PATCH v9 10/10] btrace: Extend ptwrite event decoding Felix Willgerodt
@ 2023-07-06 16:37 ` Tom Tromey
  10 siblings, 0 replies; 33+ messages in thread
From: Tom Tromey @ 2023-07-06 16:37 UTC (permalink / raw)
  To: Felix Willgerodt via Gdb-patches
  Cc: markus.t.metzger, simark, Felix Willgerodt

>>>>> Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org> writes:

> I changed the following commits, mainly based on comments from Simon (thanks!):
[...]

FWIW I skimmed through this series and sent a couple of comments.
Otherwise it looks good to me.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 10/10] btrace: Extend ptwrite event decoding.
  2023-07-04 12:36 ` [PATCH v9 10/10] btrace: Extend ptwrite event decoding Felix Willgerodt
  2023-07-04 12:56   ` Eli Zaretskii
@ 2023-07-06 16:46   ` Tom Tromey
  2023-07-13 12:34     ` Willgerodt, Felix
  1 sibling, 1 reply; 33+ messages in thread
From: Tom Tromey @ 2023-07-06 16:46 UTC (permalink / raw)
  To: Felix Willgerodt via Gdb-patches
  Cc: markus.t.metzger, simark, Felix Willgerodt

>>>>> Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org> writes:

> diff --git a/gdb/NEWS b/gdb/NEWS
> index fd42864c692..156e5c9c5f0 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -226,6 +226,13 @@ info main
 
>  *** Changes in GDB 13
 
> +* GDB now supports printing of ptwrite payloads from the Intel Processor
> +  Trace during 'record instruction-history', 'record function-call-history'
> +  and all stepping commands.  The payload is also accessible in Python as a
> +  RecordAuxiliary object.  Printing is customizable via a ptwrite filter
> +  function in Python.  By default, the raw ptwrite payload is printed for
> +  each ptwrite that is encountered.
> +

This seems like it should be in the GDB 14 section.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v9 10/10] btrace: Extend ptwrite event decoding.
  2023-07-06 16:46   ` Tom Tromey
@ 2023-07-13 12:34     ` Willgerodt, Felix
  0 siblings, 0 replies; 33+ messages in thread
From: Willgerodt, Felix @ 2023-07-13 12:34 UTC (permalink / raw)
  To: Tom Tromey, Felix Willgerodt via Gdb-patches; +Cc: Metzger, Markus T, simark

> -----Original Message-----
> From: Tom Tromey <tom@tromey.com>
> Sent: Donnerstag, 6. Juli 2023 18:47
> To: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Metzger, Markus T <markus.t.metzger@intel.com>; simark@simark.ca;
> Willgerodt, Felix <felix.willgerodt@intel.com>
> Subject: Re: [PATCH v9 10/10] btrace: Extend ptwrite event decoding.
> 
> >>>>> Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org> writes:
> 
> > diff --git a/gdb/NEWS b/gdb/NEWS
> > index fd42864c692..156e5c9c5f0 100644
> > --- a/gdb/NEWS
> > +++ b/gdb/NEWS
> > @@ -226,6 +226,13 @@ info main
> 
> >  *** Changes in GDB 13
> 
> > +* GDB now supports printing of ptwrite payloads from the Intel Processor
> > +  Trace during 'record instruction-history', 'record function-call-history'
> > +  and all stepping commands.  The payload is also accessible in Python as a
> > +  RecordAuxiliary object.  Printing is customizable via a ptwrite filter
> > +  function in Python.  By default, the raw ptwrite payload is printed for
> > +  each ptwrite that is encountered.
> > +
> 
> This seems like it should be in the GDB 14 section.
> 
> Tom

Right, thanks for catching that. I didn't see any problems when rebasing it and didn't double check. I moved it to the new section.

Felix
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v9 09/10] btrace, python: Enable ptwrite filter registration.
  2023-07-06 16:31   ` Tom Tromey
@ 2023-07-13 12:34     ` Willgerodt, Felix
  0 siblings, 0 replies; 33+ messages in thread
From: Willgerodt, Felix @ 2023-07-13 12:34 UTC (permalink / raw)
  To: Tom Tromey, Felix Willgerodt via Gdb-patches; +Cc: Metzger, Markus T, simark

> -----Original Message-----
> From: Tom Tromey <tom@tromey.com>
> Sent: Donnerstag, 6. Juli 2023 18:31
> To: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Metzger, Markus T <markus.t.metzger@intel.com>; simark@simark.ca;
> Willgerodt, Felix <felix.willgerodt@intel.com>
> Subject: Re: [PATCH v9 09/10] btrace, python: Enable ptwrite filter
> registration.
> 
> >>>>> Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> writes:
> 
> > By default GDB will be printing the hex payload of the ptwrite package as
> > auxiliary information.  To customize this, the user can register a ptwrite
> > filter function in python, that takes the payload and the PC as arguments
> and
> > returns a string which will be printed instead.  Registering the filter
> > function is done using a factory pattern to make per-thread filtering easier.
> 
> Thank you for the patch.
> 
> > +  /* Function pointer to the ptwrite callback.  Returns the string returned
> > +     by the ptwrite filter function.  */
> > +  gdb::optional<std::string> (*ptw_callback_fun) (const uint64_t payload,
> > +						  const uint64_t ip,
> > +						  const void *ptw_context)
> > +						    = nullptr;
> > +
> > +  /* Context for the ptw_callback_fun.  */
> > +  void *ptw_context = nullptr;
> 
> I tend to think it's better to use std::function here, rather than the
> C-style pointer-and-data approach.

I had this comment before in this series. 
In the end I need to call PyObject_CallFunctionObjArgs() with ptw_context.
This function requires a function pointer, as it is C, not C++.

Then there is also the topic of the GDB extension language interface, if you
are also talking about ptw_callback_fun.
There GDB also uses function pointers right now. We can of course change
that, but I think that should not be part of this series.


> > diff --git a/gdb/python/lib/gdb/ptwrite.py
> b/gdb/python/lib/gdb/ptwrite.py
> 
> I gather the new stuff is documented in the next patch.

Correct.

> > +# _ptwrite_filter contains the per thread copies of the filter function.
> > +# The keys are tuples of inferior id and thread id.
> > +# The filter functions are created for each thread by calling the
> > +# _ptwrite_filter_factory.
> > +_ptwrite_filter = {}
> 
> It seems like when an inferior or thread is destroyed, the entries
> should be removed from this map.

That is done by _ptwrite_exit_handler being registered as a thread_exit handler.

> > +  gdbpy_ref<> py_payload (PyLong_FromUnsignedLongLong (payload));
> > +  gdbpy_ref<> py_ip (PyLong_FromUnsignedLongLong (ip));
> 
> Both of these calls require null checks.

Thanks, I will add those.

> > +  gdbpy_ref<> py_result (PyObject_CallFunctionObjArgs ((PyObject *)
> ptw_filter,
> > +							py_payload.get (),
> > +							py_ip.get (),
> > +							nullptr));
> > +
> > +  if (PyErr_Occurred ())
> 
> It's more idiomatic to check == nullptr than PyErr_Occurred.

Will do.

> > +  result = gdbpy_obj_to_string (py_result.get ()).get ();
> > +
> > +  if (PyErr_Occurred ())
> 
> Here too.

Thanks! This actually made me realize a bigger problem.
gdbpy_obj_to_string can return nullptr, and I try to assign it to a std::string.

Now I need to think if I should just make everything a
gdb::unique_xmalloc_ptr<char> again instead of using gdb::optional<std::string>
or whether I just copy or std::move the string I get.

Felix
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v9 06/10] python: Add clear() to gdb.Record.
  2023-07-06 16:11   ` Tom Tromey
@ 2023-07-13 12:34     ` Willgerodt, Felix
  2023-07-13 16:45       ` Tom Tromey
  0 siblings, 1 reply; 33+ messages in thread
From: Willgerodt, Felix @ 2023-07-13 12:34 UTC (permalink / raw)
  To: Tom Tromey, Felix Willgerodt via Gdb-patches; +Cc: Metzger, Markus T, simark

> -----Original Message-----
> From: Tom Tromey <tom@tromey.com>
> Sent: Donnerstag, 6. Juli 2023 18:12
> To: Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Metzger, Markus T <markus.t.metzger@intel.com>; simark@simark.ca;
> Willgerodt, Felix <felix.willgerodt@intel.com>
> Subject: Re: [PATCH v9 06/10] python: Add clear() to gdb.Record.
> 
> >>>>> Felix Willgerodt via Gdb-patches <gdb-patches@sourceware.org> writes:
> 
> > This function allows to clear the trace data from python, forcing to
> > re-decode the trace for successive commands.
> > This will be used in future ptwrite patches, to trigger re-decoding when
> > the ptwrite filter changes.
> 
> > +PyObject *
> > +recpy_bt_clear (PyObject *self, PyObject *args)
> > +{
> > +  const recpy_record_object * const record = (recpy_record_object *) self;
> > +  thread_info *const tinfo = record->thread;
> 
> Normally in the Python layer, some care must be taken to ensure that
> something sensible happens when a Python object outlives some underlying
> gdb object.  That is why some types have an 'is_valid' method and why
> there are the various *_REQUIRE_VALID macros.
> 
> It isn't a problem with this patch per se but it seems to me that this
> code does not handle this situation properly.
> 
> Tom

Thanks for the review, I am not sure I understand your point completely.

In this patch, standalone, I don't see any such problem, so you are probably
referring to the whole series.
Note that there is already "maintenance btrace clear" in CLI. So if anything
bad could happen, it would already be exposed by that command as well.
But yes, that is a maintenance command so maybe not 100% comparable.

Why we need this patch in this series, is that once a function call history
or instruction call history is decoded, it will not be re-decoded until you
continue to the next BP and re-issue the command.
And that makes some sense, as the decoding can be costly.

Now, if a user registers a new ptwrite filter, and we don't re-decode the
trace, he will be confused. As he still sees the old trace and not the
output of his newly registered filter function. We could state that that
is a limitation, or check for this and warn the user. But I decided to instead
clear the trace data to force re-decoding the function and instruction
history. 
I tested this a bit, and you can too with upstream using the maintenance
command. I didn't see any problems, any subsequent commands would
use the new trace data. And any gdb python objects would also fetch that
new trace data or print an error if the trace data is empty.

Felix
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v9 06/10] python: Add clear() to gdb.Record.
  2023-07-13 12:34     ` Willgerodt, Felix
@ 2023-07-13 16:45       ` Tom Tromey
  2023-07-14 11:07         ` Willgerodt, Felix
  0 siblings, 1 reply; 33+ messages in thread
From: Tom Tromey @ 2023-07-13 16:45 UTC (permalink / raw)
  To: Willgerodt, Felix via Gdb-patches
  Cc: Tom Tromey, Willgerodt, Felix, Metzger, Markus T, simark

>> > +PyObject *
>> > +recpy_bt_clear (PyObject *self, PyObject *args)
>> > +{
>> > +  const recpy_record_object * const record = (recpy_record_object *) self;
>> > +  thread_info *const tinfo = record->thread;

>> Normally in the Python layer, some care must be taken to ensure that
>> something sensible happens when a Python object outlives some underlying
>> gdb object.  That is why some types have an 'is_valid' method and why
>> there are the various *_REQUIRE_VALID macros.

> Thanks for the review, I am not sure I understand your point completely.

> In this patch, standalone, I don't see any such problem, so you are probably
> referring to the whole series.

What I mean is consider this sequence:

* Run some inferior

* Use the py-record-btrace code -- however you do that -- to create one
  of these objects and stash it in some global.

* Kill or restart the inferior.

* Do any operation on that stored global that references
  btpy_list_object::thread

I'd expect a crash or UAF in this situation because the thread has been
destroyed.

In other Python-layer modules, care is taken to decouple the lifetime of
the Python object wrappers from their underlying gdb objects.  This way,
methods on such objects raise a Python exception rather than causing a
gdb crash.

For example, the gdb.InferiorThread type has this exact same setup, but
solved the problem by arranging to clear the 'thread' member when the
thread dies:

  gdb::observers::thread_exit.attach (delete_thread_object, "py-inferior");

and then all the InferiorThread methods call this:

  THPY_REQUIRE_VALID (thread_obj);

to ensure that the underlying thread exists.

Tom

^ permalink raw reply	[flat|nested] 33+ messages in thread

* RE: [PATCH v9 06/10] python: Add clear() to gdb.Record.
  2023-07-13 16:45       ` Tom Tromey
@ 2023-07-14 11:07         ` Willgerodt, Felix
  0 siblings, 0 replies; 33+ messages in thread
From: Willgerodt, Felix @ 2023-07-14 11:07 UTC (permalink / raw)
  To: Tom Tromey, Willgerodt, Felix via Gdb-patches; +Cc: Metzger, Markus T, simark

> -----Original Message-----
> From: Tom Tromey <tom@tromey.com>
> Sent: Donnerstag, 13. Juli 2023 18:45
> To: Willgerodt, Felix via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Tom Tromey <tom@tromey.com>; Willgerodt, Felix
> <felix.willgerodt@intel.com>; Metzger, Markus T <markus.t.metzger@intel.com>;
> simark@simark.ca
> Subject: Re: [PATCH v9 06/10] python: Add clear() to gdb.Record.
> 
> >> > +PyObject *
> >> > +recpy_bt_clear (PyObject *self, PyObject *args)
> >> > +{
> >> > +  const recpy_record_object * const record = (recpy_record_object *) self;
> >> > +  thread_info *const tinfo = record->thread;
> 
> >> Normally in the Python layer, some care must be taken to ensure that
> >> something sensible happens when a Python object outlives some underlying
> >> gdb object.  That is why some types have an 'is_valid' method and why
> >> there are the various *_REQUIRE_VALID macros.
> 
> > Thanks for the review, I am not sure I understand your point completely.
> 
> > In this patch, standalone, I don't see any such problem, so you are probably
> > referring to the whole series.
> 
> What I mean is consider this sequence:
> 
> * Run some inferior
> 
> * Use the py-record-btrace code -- however you do that -- to create one
>   of these objects and stash it in some global.
> 
> * Kill or restart the inferior.
> 
> * Do any operation on that stored global that references
>   btpy_list_object::thread
> 
> I'd expect a crash or UAF in this situation because the thread has been
> destroyed.

The code does check if we have a valid btinfo object (and therefore thread)
and errors out.
In this experiments, I saved some globals, ran the program till exit
and then went back to python again:


>>> r = gdb.current_recording()
>>> h = r.instruction_history
>>> hf = r.function_call_history
>>> x = h[0]
>>> y = hf[2]
>>> quit
(gdb) c
Continuing.
[Inferior 1 (process 119679) exited with code 011]
(gdb) pi
>>> y
<gdb.RecordFunctionSegment object at 0x7f3e9c35be10>
>>> x
<gdb.RecordInstruction object at 0x7f3e9c35be70>
>>> h
<gdb.BtraceObjectList object at 0x7f3e9c1bd530>
>>> hf
<gdb.BtraceObjectList object at 0x7f3e9c1bd7f0>
>>> y.symbol
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
gdb.error: No such function segment.
>>> x.decoded
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
gdb.error: No such instruction.
>>> h[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
gdb.error: No such instruction.
>>> hf[0]
<gdb.RecordFunctionSegment object at 0x7f3e9c35bd50>
>>> hf[0].symbol
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
gdb.error: No such function segment.


You see the same thing if you use btrace.clear() or maint btrace clear.

The same checks are added in my patch for the aux object. See the function
recpy_bt_aux_data. And the functions btrace_insn_from_recpy_insn and
btrace_func_from_recpy_func in upstream.

Also note that this behavior wasn't added by my patch series.
It merely adds a new object type with the same behavior.

Felix
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2023-07-14 11:07 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-04 12:35 [PATCH v9 00/10] Extensions for PTWRITE Felix Willgerodt
2023-07-04 12:35 ` [PATCH v9 01/10] btrace: Introduce auxiliary instructions Felix Willgerodt
2023-07-04 12:44   ` Eli Zaretskii
2023-07-04 12:35 ` [PATCH v9 02/10] btrace: Enable auxiliary instructions in record instruction-history Felix Willgerodt
2023-07-04 12:45   ` Eli Zaretskii
2023-07-04 12:35 ` [PATCH v9 03/10] btrace: Enable auxiliary instructions in record function-call-history Felix Willgerodt
2023-07-04 12:47   ` Eli Zaretskii
2023-07-04 12:35 ` [PATCH v9 04/10] btrace: Handle stepping and goto for auxiliary instructions Felix Willgerodt
2023-07-04 12:35 ` [PATCH v9 05/10] python: Introduce gdb.RecordAuxiliary class Felix Willgerodt
2023-07-04 12:52   ` Eli Zaretskii
2023-07-05 10:04     ` Willgerodt, Felix
2023-07-05 11:37       ` Eli Zaretskii
2023-07-04 12:35 ` [PATCH v9 06/10] python: Add clear() to gdb.Record Felix Willgerodt
2023-07-04 12:46   ` Eli Zaretskii
2023-07-05 10:03     ` Willgerodt, Felix
2023-07-05 11:35       ` Eli Zaretskii
2023-07-06 16:11   ` Tom Tromey
2023-07-13 12:34     ` Willgerodt, Felix
2023-07-13 16:45       ` Tom Tromey
2023-07-14 11:07         ` Willgerodt, Felix
2023-07-04 12:35 ` [PATCH v9 07/10] btrace, gdbserver: Add ptwrite to btrace_config_pt Felix Willgerodt
2023-07-04 12:49   ` Eli Zaretskii
2023-07-05 10:04     ` Willgerodt, Felix
2023-07-04 12:35 ` [PATCH v9 08/10] btrace, linux: Enable ptwrite packets Felix Willgerodt
2023-07-04 12:35 ` [PATCH v9 09/10] btrace, python: Enable ptwrite filter registration Felix Willgerodt
2023-07-06 16:31   ` Tom Tromey
2023-07-13 12:34     ` Willgerodt, Felix
2023-07-04 12:36 ` [PATCH v9 10/10] btrace: Extend ptwrite event decoding Felix Willgerodt
2023-07-04 12:56   ` Eli Zaretskii
2023-07-05 10:04     ` Willgerodt, Felix
2023-07-06 16:46   ` Tom Tromey
2023-07-13 12:34     ` Willgerodt, Felix
2023-07-06 16:37 ` [PATCH v9 00/10] Extensions for PTWRITE Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).