diff options
author | Felix Willgerodt <felix.willgerodt@intel.com> | 2019-02-18 15:50:49 +0100 |
---|---|---|
committer | Felix Willgerodt <felix.willgerodt@intel.com> | 2024-08-14 11:20:57 +0200 |
commit | 3bf62223f0f5591c70523e363a496dba6c699e3a (patch) | |
tree | 2d1f60312520648fd630cb563c56b7f87fe7326c /gdb | |
parent | 6be9971c93f3bbcd4b779e5591697748da6b093e (diff) | |
download | gdb-3bf62223f0f5591c70523e363a496dba6c699e3a.zip gdb-3bf62223f0f5591c70523e363a496dba6c699e3a.tar.gz gdb-3bf62223f0f5591c70523e363a496dba6c699e3a.tar.bz2 |
btrace: Extend ptwrite event decoding.
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>
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/NEWS | 7 | ||||
-rw-r--r-- | gdb/btrace.c | 73 | ||||
-rw-r--r-- | gdb/doc/python.texi | 151 | ||||
-rw-r--r-- | gdb/testsuite/gdb.btrace/i386-ptwrite.S | 550 | ||||
-rw-r--r-- | gdb/testsuite/gdb.btrace/ptwrite.c | 39 | ||||
-rw-r--r-- | gdb/testsuite/gdb.btrace/ptwrite.exp | 201 | ||||
-rw-r--r-- | gdb/testsuite/gdb.btrace/x86_64-ptwrite.S | 544 | ||||
-rw-r--r-- | gdb/testsuite/lib/gdb.exp | 73 |
8 files changed, 1638 insertions, 0 deletions
@@ -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. diff --git a/gdb/btrace.c b/gdb/btrace.c index d493fbe..95ff27c 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -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) */ diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 83e8c60..bb1f205 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -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 index 0000000..5c649cf --- /dev/null +++ b/gdb/testsuite/gdb.btrace/i386-ptwrite.S @@ -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 index 0000000..e10b885 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/ptwrite.c @@ -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 index 0000000..0970d31 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/ptwrite.exp @@ -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 index 0000000..be4d204 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S @@ -0,0 +1,544 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 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 diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index c4e322b..1c49b6a 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -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. |