> -----Original Message-----
> From: Simon Marchi <simark@simark.ca>
> Sent: Freitag, 24. März 2023 16:41
> To: Willgerodt, Felix <felix.willgerodt@intel.com>; gdb-
> patches@sourceware.org
> Subject: Re: [PATCH v8 10/10] btrace: Extend ptwrite event decoding.
>
> On 3/21/23 11:46, Felix Willgerodt via Gdb-patches wrote:
> > 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 | 54 +++
> > gdb/config.in | 3 +
> > gdb/configure | 11 +
> > gdb/doc/python.texi | 150 ++++++
> > gdb/testsuite/gdb.btrace/i386-ptwrite.S | 550
> ++++++++++++++++++++++
> > gdb/testsuite/gdb.btrace/ptwrite.c | 39 ++
> > gdb/testsuite/gdb.btrace/ptwrite.exp | 200 ++++++++
> > 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, 1646 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 cc262f1f8a6..5dd05867f2a 100644
> > --- a/gdb/NEWS
> > +++ b/gdb/NEWS
> > @@ -106,6 +106,13 @@ show always-read-ctf
> >
> > *** 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 37dd0b666d8..db0d0e291d9 100644
> > --- a/gdb/btrace.c
> > +++ b/gdb/btrace.c
> > @@ -1253,6 +1253,54 @@ 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;
> > + 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_callback_fun is nullptr, the string will always be empty, and the
> data not shown? This means that in a build without Python, the data
> will never be shown?
>
> I think a better approach would be to handle the default case (print as
> hex) here, instead of in a Python function. I think that
> ptw_callback_fun should return a gdb::optional<std::string>. If the
> optional is instantiated (including containing an empty string), use
> that value. If ptw_callback_fun is nullptr (perhaps because GDB was
> built with no Python support), or if the returned optional is not
> instantiated (perhaps because the user did not register any filter),
> generate the default (print as hex) here.
>
We wanted the user to be able to register None as a listener. But I think
that might still be from a time where we didn't implement
the /a modifiers for the instruction/function-history CLI commands to
enable not printing the strings.
I think your suggestion makes sense. I guess in that case we should try
to get rid of the current default filter in Python. To not have two places
in the code that do the same thing.
> > +
> > + if (ptw_string.empty ())
> > + break;
> > +
> > + btinfo->aux_data.emplace_back (ptw_string);
>
> Since you don't need ptw_string below, you can std::move it in the
> vector.
Right, I will do that.
> > +@end defun
> > +
> > +@findex gdb.ptwrite.get_filter
> > +@defun get_filter ()
> > +Return the currently active @code{PTWRITE} filter function.
> > +@end defun
> > +
> > +@findex gdb.ptwrite.default_filter
> > +@defun default_filter (@var{payload}, @var{ip})
> > +The filter function active by default. It prints the payload in hexadecimal
> > +format.
> > +@end defun
> > +
> > +@value{GDBN} creates a new copy of the filter function for each thread
> to
> > +allow for independent internal states. There is no support for registering
>
> Ok, I guess that answers my question about deepcopy. I think it would
> be good to say that the copy is done using the deepcopy module/function.
>
I will add that.
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
@@ -106,6 +106,13 @@ show always-read-ctf
*** 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
@@ -1253,6 +1253,54 @@ 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;
+ 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.empty ())
+ break;
+
+ btinfo->aux_data.emplace_back (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 +3029,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) */
}
}
@@ -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
@@ -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
@@ -7145,6 +7145,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
@@ -7335,3 +7336,152 @@ 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 [42]
+14 0x00400751 <ptwrite64+21>: mov -0x8(%rbp),%rbx
+(gdb) record function-call-history
+1 main
+2 ptwrite64
+ [42]
+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 via @code{gdb.ptwrite.register_filter} as the @code{PTWRITE}
+filter function. This function will be called with the @code{PTWRITE}
+payload and PC as arguments during trace decoding.
+
+@findex gdb.ptwrite.register_filter
+@defun register_filter (@var{filter})
+Used to register the @code{PTWRITE} filter. The filter can be any callable
+object that accepts two arguments, the payload and PC. It can return
+a string, which will be printed by @value{GDBN} during the aforementioned
+commands, or @code{None}, resulting in no output. @code{None} can also be
+registered to deactivate printing.
+@end defun
+
+@findex gdb.ptwrite.get_filter
+@defun get_filter ()
+Return the currently active @code{PTWRITE} filter function.
+@end defun
+
+@findex gdb.ptwrite.default_filter
+@defun default_filter (@var{payload}, @var{ip})
+The filter function active by default. It prints the payload in hexadecimal
+format.
+@end defun
+
+@value{GDBN} creates a new copy of the filter function for each thread to
+allow for independent internal states. There is no support for registering
+different filters for different threads. The filter can however
+distinguish between multiple threads with the help of
+@code{gdb.selected_thread().global_num} (@pxref{Threads In Python}) or
+similar. For example:
+
+@smallexample
+@group
+(gdb) python-interactive
+>>> class my_filter():
+... def __init__(self):
+... self.var = 0
+... def __call__(self, payload, ip):
+... if gdb.selected_thread().global_num == 1:
+... self.var += 1
+... return f"counter: @{self.var@}, ip: @{ip:#x@}"
+... else:
+... return None
+...
+>>> import gdb.ptwrite
+>>> gdb.ptwrite.register_filter(my_filter())
+>>>
+@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)
+13 task(void*)
+14 ptwrite32(unsigned int)
+@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.
new file mode 100644
@@ -0,0 +1,550 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2022 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
new file mode 100644
@@ -0,0 +1,39 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2021 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;
+}
new file mode 100644
@@ -0,0 +1,200 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2021 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 \\\[42\\\]" \
+ ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t \\\[43\\\].*" \
+ ]
+
+ 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\\\[42\\\]" \
+ "3\tmain" \
+ "4\tptwrite2" \
+ "\t\t\\\[43\\\]" \
+ ]
+
+ 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" "No such instruction\."
+ gdb_test "record goto 9" ".*ptwrite.* at .*"
+ gdb_test "stepi" ".*\\\[42\\\].*"
+ gdb_test "reverse-stepi" ".*\\\[42\\\].*"
+ gdb_test "continue" [multi_line \
+ ".*\\\[42\\\]" \
+ "\\\[43\\\].*" \
+ ]
+ gdb_test "reverse-continue" [multi_line \
+ ".*\\\[43\\\]" \
+ "\\\[42\\\].*" \
+ ]
+}
+
+# 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" \
+ "42" \
+ "nop.*" \
+ "mov -0x4\\\(%(e|r)bp\\\),%(e|r)ax" \
+ "ptwrite %eax" \
+ "43" \
+ "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" "" \
+ "import gdb.ptwrite" "" \
+ "gdb.ptwrite.register_filter(my_filter)" "" \
+ "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
+with_test_prefix "None" {
+ gdb_test_multiline "register filter in python" \
+ "python" "" \
+ "import gdb.ptwrite" "" \
+ "gdb.ptwrite.register_filter(None)" "" \
+ "end" ""
+
+ gdb_test "record instruction-history 1" [multi_line \
+ ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:.*" \
+ "\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
+ "\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:.*" \
+ ]
+}
+
+### 2.3 Lambdas as filter
+with_test_prefix "Lambdas" {
+ gdb_test_multiline "register filter in python" \
+ "python" "" \
+ "import gdb.ptwrite" "" \
+ "gdb.ptwrite.register_filter(lambda payload, ip: \"{}\".format(payload + 2))" "" \
+ "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(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"
+}
new file mode 100644
@@ -0,0 +1,544 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2022 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
@@ -3939,6 +3939,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.
@@ -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
@@ -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
@@ -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