]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
btrace: Extend ptwrite event decoding.
authorFelix Willgerodt <felix.willgerodt@intel.com>
Mon, 18 Feb 2019 14:50:49 +0000 (15:50 +0100)
committerFelix Willgerodt <felix.willgerodt@intel.com>
Wed, 14 Aug 2024 09:20:57 +0000 (11:20 +0200)
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.

Approved-By: Markus Metzger <markus.t.metzger@intel.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
gdb/NEWS
gdb/btrace.c
gdb/doc/python.texi
gdb/testsuite/gdb.btrace/i386-ptwrite.S [new file with mode: 0644]
gdb/testsuite/gdb.btrace/ptwrite.c [new file with mode: 0644]
gdb/testsuite/gdb.btrace/ptwrite.exp [new file with mode: 0644]
gdb/testsuite/gdb.btrace/x86_64-ptwrite.S [new file with mode: 0644]
gdb/testsuite/lib/gdb.exp

index dfcabb1677e11dd027065907525c60f3e99522ba..81aa8af233862fd462f134b3169e293b71e2694a 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,13 @@
 
 *** Changes since GDB 15
 
+* 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.
+
 * Python API
 
   ** Added gdb.record.clear.  Clears the trace data of the current recording.
index d493fbec65a6065e64a8c8ca9c9b82f40df054d3..95ff27cc4fe24d0544f5ab61ba8b79a97132f13c 100644 (file)
@@ -41,6 +41,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;
@@ -1204,6 +1205,24 @@ pt_btrace_insn (const struct pt_insn &insn)
          pt_btrace_insn_flags (insn)};
 }
 
+#if defined (HAVE_PT_INSN_EVENT)
+/* Helper for events that will result in an aux_insn.  */
+
+static void
+handle_pt_aux_insn (btrace_thread_info *btinfo, btrace_function *bfun,
+                   std::string &aux_str, CORE_ADDR ip)
+{
+  btinfo->aux_data.emplace_back (std::move (aux_str));
+  bfun = ftrace_update_function (btinfo, ip);
+
+  btrace_insn insn {btinfo->aux_data.size () - 1, 0,
+                   BTRACE_INSN_AUX, 0};
+
+  ftrace_update_insns (bfun, insn);
+}
+
+#endif /* defined (HAVE_PT_INSN_EVENT) */
+
 /* Handle instruction decode events (libipt-v2).  */
 
 static int
@@ -1252,6 +1271,60 @@ 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 pc = 0;
+           std::optional<std::string> ptw_string;
+
+           /* Lookup the PC if available.  The event often doesn't provide
+              one, so we look into the last function segment as well.
+              Looking further back makes limited sense for ptwrite.  */
+           if (event.ip_suppressed == 0)
+             pc = event.variant.ptwrite.ip;
+           else if (!btinfo->functions.empty ())
+             {
+               std::vector<btrace_insn> &insns
+                 = btinfo->functions.back ().insn;
+               for (auto insn = insns.rbegin (); insn != insns.rend ();
+                    ++insn)
+                 {
+                   switch (insn->iclass)
+                   {
+                   case BTRACE_INSN_AUX:
+                     continue;
+
+                   case BTRACE_INSN_OTHER:
+                   case BTRACE_INSN_CALL:
+                   case BTRACE_INSN_RETURN:
+                   case BTRACE_INSN_JUMP:
+                     pc = insn->pc;
+                     break;
+                   /* No default to rely on compiler warnings.  */
+                   }
+                   break;
+                 }
+             }
+
+           if (pc == 0)
+             warning (_("Failed to determine the PC for ptwrite."));
+
+           if (btinfo->ptw_callback_fun != nullptr)
+             ptw_string
+               = btinfo->ptw_callback_fun (event.variant.ptwrite.payload,
+                                           pc, 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);
+
+           handle_pt_aux_insn (btinfo, bfun, *ptw_string, pc);
+
+           break;
+         }
+#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */
        }
     }
 #endif /* defined (HAVE_PT_INSN_EVENT) */
index 83e8c6037eaee92968e4c58d6e56ee7b3c759d60..bb1f205d4fe087a0a9a8d5695b323529c5ea6484 100644 (file)
@@ -8224,6 +8224,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
@@ -8414,3 +8415,153 @@ 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} intrinsics for it are:
+@smallexample
+void _ptwrite32 (unsigned int a)
+void _ptwrite64 (unsigned __int64 a)
+@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 (@pxref{Recordings In Python}).
+
+@exdent Sample program:
+@smallexample
+@group
+#include <immintrin.h>
+
+void
+ptwrite64 (unsigned long long value)
+@{
+  _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.  The function 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 @value{GDBN}.
+
+@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 (file)
index 0000000..5c649cf
--- /dev/null
@@ -0,0 +1,550 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2024 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 (file)
index 0000000..e10b885
--- /dev/null
@@ -0,0 +1,39 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 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 (file)
index 0000000..0970d31
--- /dev/null
@@ -0,0 +1,201 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2024 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 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  \\\[0x42\\\]" \
+       "3\tmain" \
+       "4\tptwrite2" \
+       "\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 (file)
index 0000000..be4d204
--- /dev/null
@@ -0,0 +1,544 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2024 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
index c4e322b59a053fce942288123ab3e4092cc4f218..1c49b6a36d77115d0437d9c3f30cf3654eace556 100644 (file)
@@ -4299,6 +4299,79 @@ 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 {
+       #include <immintrin.h>
+
+       int
+       main ()
+       {
+         _ptwrite32 (0x42);
+         return 0;
+       }
+    }
+
+    set compile_flags "additional_flags=-mptwrite"
+    if {![gdb_simple_compile $me $src executable $compile_flags]} {
+       return 0
+    }
+
+    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 0
+    gdb_test_multiple "next" "$me: next" {
+       -re -wrap ".*Illegal instruction.*" {
+           verbose -log "$me:  ptwrite instruction support not detected."
+       }
+       -re -wrap ".*$inferior_exited_re normally.*" {
+           verbose -log "$me:  ptwrite support not detected."
+       }
+       -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 -wrap "" {
+               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.