From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by sourceware.org (Postfix) with ESMTPS id 1421D38344D3 for ; Wed, 22 Jun 2022 11:46:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1421D38344D3 X-IronPort-AV: E=McAfee;i="6400,9594,10385"; a="260825247" X-IronPort-AV: E=Sophos;i="5.92,212,1650956400"; d="scan'208";a="260825247" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jun 2022 04:46:39 -0700 X-IronPort-AV: E=Sophos;i="5.92,212,1650956400"; d="scan'208";a="677499580" Received: from mulvlfelix.iul.intel.com (HELO localhost) ([172.28.48.92]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jun 2022 04:46:37 -0700 From: Felix Willgerodt To: gdb-patches@sourceware.org, markus.t.metzger@intel.com Subject: [PATCH v5 10/10] btrace: Extend ptwrite event decoding. Date: Wed, 22 Jun 2022 13:43:40 +0200 Message-Id: <20220622114340.55830-11-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.34.3 In-Reply-To: <20220622114340.55830-1-felix.willgerodt@intel.com> References: <20220622114340.55830-1-felix.willgerodt@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Jun 2022 11:47:02 -0000 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 | 6 + gdb/btrace.c | 53 +++ gdb/config.in | 3 + gdb/configure | 11 + gdb/doc/python.texi | 150 +++++++++ gdb/testsuite/gdb.btrace/i386-ptwrite.S | 379 ++++++++++++++++++++++ gdb/testsuite/gdb.btrace/ptwrite.c | 37 +++ gdb/testsuite/gdb.btrace/ptwrite.exp | 219 +++++++++++++ gdb/testsuite/gdb.btrace/x86_64-ptwrite.S | 374 +++++++++++++++++++++ gdb/testsuite/lib/gdb.exp | 74 +++++ gdbsupport/common.m4 | 2 + gdbsupport/config.in | 3 + gdbsupport/configure | 11 + 13 files changed, 1322 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 5576c355b7a..b6b2417b360 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,12 @@ *** Changes since GDB 12 +* GDB now supports printing of ptwrite payloads from the Intel Processor + Trace during 'record instruction-history', 'record function-call-history', + all stepping commands and in Python. Printing is customizable via a + ptwrite filter function in Python. By default, the raw ptwrite + payload is printed for each ptwrite that is encountered. + * "info breakpoints" now displays enabled breakpoint locations of disabled breakpoints as in the "y-" state. For example: diff --git a/gdb/btrace.c b/gdb/btrace.c index d8c4b77bbc5..b5e18412458 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -1253,6 +1253,53 @@ 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_filter); + + 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 = { 0 }; + ptw_insn.aux_data_index = btinfo->aux_data.size () - 1; + ptw_insn.flags = flags; + ptw_insn.iclass = BTRACE_INSN_AUX; + + 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_AUX_DECODED; + ftrace_update_insns (bfun, ptw_insn); + + break; + } +#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */ } } #endif /* defined (HAVE_PT_INSN_EVENT) */ @@ -2979,6 +3026,12 @@ pt_print_packet (const struct pt_packet *packet) case ppt_mnt: gdb_printf (("mnt %" PRIx64 ""), packet->payload.mnt.payload); break; + +#if defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) + case ppt_ptw: + gdb_printf (("ptw %" PRIx64 ""), packet->payload.ptw.payload); + break; +#endif /* defined (HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE) */ } } diff --git a/gdb/config.in b/gdb/config.in index a4975c68aad..d572c51ec79 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -460,6 +460,9 @@ /* Define to 1 if `pl_tdname' is a member of `struct ptrace_lwpinfo'. */ #undef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME +/* Define to 1 if `variant.ptwrite' is a member of `struct pt_event'. */ +#undef HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE + /* Define to 1 if `enabled' is a member of `struct pt_insn'. */ #undef HAVE_STRUCT_PT_INSN_ENABLED diff --git a/gdb/configure b/gdb/configure index 1b821390801..7e2d23c361e 100755 --- a/gdb/configure +++ b/gdb/configure @@ -15327,6 +15327,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 +" +if test "x$ac_cv_member_struct_pt_event_variant_ptwrite" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE 1 +_ACEOF + + fi LIBS=$save_LIBS diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index a25a49fcb8a..b1d3a0587c0 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -6997,6 +6997,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 @@ -7187,3 +7188,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 : ptwrite %rbx +13 [42] +14 0x00400751 : 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 ptwrite +auxiliary information. A custom Python function can be registered via +@code{gdb.ptwrite.register_filter} as the ptwrite filter function. +This function will be called with the ptwrite payload and PC as arguments +during trace decoding. + +@findex gdb.ptwrite.register_filter +@defun register_filter (@var{filter}) +Used to register the 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 () +Returns the currently active 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. diff --git a/gdb/testsuite/gdb.btrace/i386-ptwrite.S b/gdb/testsuite/gdb.btrace/i386-ptwrite.S new file mode 100644 index 00000000000..90eb0d5eaa1 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/i386-ptwrite.S @@ -0,0 +1,379 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022 Free Software Foundation, Inc. + + Contributed by Intel Corp. + + 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 . + + + This file has been generated using gcc version 10.3.1 20210422 + (Red Hat 10.3.1-1): + gcc -S -dA -g -m32 ptwrite.c -o i386-ptwrite.S. */ + + .file "ptwrite.c" + .text +.Ltext0: + .globl ptwrite64 + .type ptwrite64, @function +ptwrite64: +.LFB0: + .file 1 "ptwrite.c" + # ptwrite.c:20:1 + .loc 1 20 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 + pushl %ebx + .cfi_offset 3, -12 + # ptwrite.c:21:3 + .loc 1 21 3 + movl 8(%ebp), %eax + movl %eax, %ebx +#APP +# 21 "ptwrite.c" 1 + PTWRITE %ebx; +# 0 "" 2 + # ptwrite.c:22:1 + .loc 1 22 1 +#NO_APP + nop + movl -4(%ebp), %ebx + leave + .cfi_restore 5 + .cfi_restore 3 + .cfi_def_cfa 4, 4 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE0: + .size ptwrite64, .-ptwrite64 + .globl ptwrite32 + .type ptwrite32, @function +ptwrite32: +.LFB1: + # ptwrite.c:26:1 + .loc 1 26 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 + pushl %ebx + .cfi_offset 3, -12 + # ptwrite.c:27:3 + .loc 1 27 3 + movl 8(%ebp), %eax + movl %eax, %ebx +#APP +# 27 "ptwrite.c" 1 + PTWRITE %ebx; +# 0 "" 2 + # ptwrite.c:28:1 + .loc 1 28 1 +#NO_APP + nop + movl -4(%ebp), %ebx + leave + .cfi_restore 5 + .cfi_restore 3 + .cfi_def_cfa 4, 4 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE1: + .size ptwrite32, .-ptwrite32 + .globl main + .type main, @function +main: +.LFB2: + # ptwrite.c:32:1 + .loc 1 32 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:33:3 + .loc 1 33 3 + pushl $66 + call ptwrite64 + addl $4, %esp + # ptwrite.c:34:3 + .loc 1 34 3 + pushl $67 + call ptwrite32 + addl $4, %esp + # ptwrite.c:36:10 + .loc 1 36 10 + movl $0, %eax + # ptwrite.c:37:1 + .loc 1 37 1 + leave + .cfi_restore 5 + .cfi_def_cfa 4, 4 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE2: + .size main, .-main +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0x87 # 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 .LASF1 # DW_AT_producer: "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -m32 -mtune=generic -march=i686 -g" + .byte 0xc # DW_AT_language + .long .LASF2 # DW_AT_name: "ptwrite.c" + .long .LASF3 # DW_AT_comp_dir: "/root/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_subprogram) + # DW_AT_external + .long .LASF4 # DW_AT_name: "main" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x1f # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .long 0x3b # DW_AT_type + .long .LFB2 # DW_AT_low_pc + .long .LFE2-.LFB2 # 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 0x3 # (DIE (0x3b) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .ascii "int\0" # DW_AT_name + .uleb128 0x4 # (DIE (0x42) DW_TAG_subprogram) + # DW_AT_external + .long .LASF5 # DW_AT_name: "ptwrite32" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x19 # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .long .LFB1 # DW_AT_low_pc + .long .LFE1-.LFB1 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .long 0x68 # DW_AT_sibling + .uleb128 0x5 # (DIE (0x58) DW_TAG_formal_parameter) + .long .LASF0 # DW_AT_name: "value" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x19 # DW_AT_decl_line + .byte 0x10 # DW_AT_decl_column + .long 0x3b # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 0 + .byte 0 # end of children of DIE 0x42 + .uleb128 0x6 # (DIE (0x68) DW_TAG_subprogram) + # DW_AT_external + .long .LASF6 # DW_AT_name: "ptwrite64" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x13 # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .long .LFB0 # DW_AT_low_pc + .long .LFE0-.LFB0 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .uleb128 0x5 # (DIE (0x7a) DW_TAG_formal_parameter) + .long .LASF0 # DW_AT_name: "value" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x13 # DW_AT_decl_line + .byte 0x10 # DW_AT_decl_column + .long 0x3b # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 0 + .byte 0 # end of children of DIE 0x68 + .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 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 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 0x8 # (DW_FORM_string) + .byte 0 + .byte 0 + .uleb128 0x4 # (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 0x5 # (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 0x6 # (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) + .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 +.LASF1: + .string "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -m32 -mtune=generic -march=i686 -g" +.LASF6: + .string "ptwrite64" +.LASF0: + .string "value" +.LASF3: + .string "/root/gdb/gdb/testsuite/gdb.btrace" +.LASF5: + .string "ptwrite32" +.LASF2: + .string "ptwrite.c" +.LASF4: + .string "main" + .ident "GCC: (GNU) 10.3.1 20210422 (Red Hat 10.3.1-1)" + .section .note.GNU-stack,"",@progbits diff --git a/gdb/testsuite/gdb.btrace/ptwrite.c b/gdb/testsuite/gdb.btrace/ptwrite.c new file mode 100644 index 00000000000..04c4f97c823 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/ptwrite.c @@ -0,0 +1,37 @@ +/* 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 . */ + +void +ptwrite64 (int value) +{ + asm volatile ("PTWRITE %0;" : : "b" (value)); +} + +void +ptwrite32 (int value) +{ + asm volatile ("PTWRITE %0;" : : "b" (value)); +} + +int +main (void) +{ + ptwrite64 (0x42); + ptwrite32 (0x43); + + return 0; +} diff --git a/gdb/testsuite/gdb.btrace/ptwrite.exp b/gdb/testsuite/gdb.btrace/ptwrite.exp new file mode 100644 index 00000000000..4ef4af8bba8 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/ptwrite.exp @@ -0,0 +1,219 @@ +# 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 . + +load_lib gdb-python.exp + +if { [skip_btrace_ptw_tests] } { + unsupported "No support for ptwrite decoding." + return -1 +} + +set opts {} + +if [info exists COMPILE] { + # make check RUNTESTFLAGS="gdb.btrace/ptwrite.exp COMPILE=1" + standard_testfile ptwrite.c + lappend opts debug +} 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 +} + +# This needs to be after runto_main +if { [skip_python_tests] } { + unsupported "Configuration doesn't support python scripting." + 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" ".*" "first next" +gdb_test "next" ".*" "second next" + +with_test_prefix "Default" { + # Test record instruction-history + gdb_test "record instruction-history 1" [multi_line \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[42\\\]" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[43\\\].*" \ + ] + + gdb_test "record instruction-history /a 1" [multi_line \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+.*" \ + ] + + # Test function call history + gdb_test "record function-call-history 1,4" [multi_line \ + "1\tmain" \ + "2\tptwrite64" \ + "\t\t\\\[42\\\]" \ + "3\tmain" \ + "4\tptwrite32" \ + "\t\t\\\[43\\\]" \ + ] + + gdb_test "record function-call-history /a 1,4" [multi_line \ + "1\tmain" \ + "2\tptwrite64" \ + "3\tmain" \ + "4\tptwrite32" \ + ] +} + +# Test payload printing during stepping +with_test_prefix "Stepping" { + + # 32-bit and 64-bit have slightly different number of instructions. + if {[is_amd64_regs_target]} { + set aux_line "10" + set ptwrite_line "9" + } else { + set aux_line "9" + set ptwrite_line "8" + } + + gdb_test "record goto $aux_line" "No such instruction\." + gdb_test "record goto $ptwrite_line" ".*ptwrite64.* at .*ptwrite.c:21.*" + 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 %eax,%ebx" \ + "ptwrite %ebx" \ + "42" \ + "nop.*" \ + "mov %eax,%ebx" \ + "ptwrite %ebx" \ + "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 :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[payload: 66, ip: $hex\\\]" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t $hex :.*" \ + ] +} + +### 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 :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t $hex :.*" \ + "\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t $hex :.*" \ + ] +} + +### 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 :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[68\\\]" \ + ".*\[0-9\]+\t $hex :\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 :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[1, 66\\\]" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[2, 67\\\].*" \ + ] "Functors: record instruction-history 1" +} diff --git a/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S b/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S new file mode 100644 index 00000000000..043c2fa2a9a --- /dev/null +++ b/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S @@ -0,0 +1,374 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022 Free Software Foundation, Inc. + + Contributed by Intel Corp. + + 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 . + + + This file has been generated using gcc version 10.3.1 20210422 + (Red Hat 10.3.1-1): + gcc -S -dA -g ptwrite.c -o x86_64-ptwrite.S. */ + + .file "ptwrite.c" + .text +.Ltext0: + .globl ptwrite64 + .type ptwrite64, @function +ptwrite64: +.LFB0: + .file 1 "ptwrite.c" + # ptwrite.c:20:1 + .loc 1 20 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 + pushq %rbx + .cfi_offset 3, -24 + movl %edi, -12(%rbp) + # ptwrite.c:21:3 + .loc 1 21 3 + movl -12(%rbp), %eax + movl %eax, %ebx +#APP +# 21 "ptwrite.c" 1 + PTWRITE %ebx; +# 0 "" 2 + # ptwrite.c:22:1 + .loc 1 22 1 +#NO_APP + nop + movq -8(%rbp), %rbx + leave + .cfi_def_cfa 7, 8 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE0: + .size ptwrite64, .-ptwrite64 + .globl ptwrite32 + .type ptwrite32, @function +ptwrite32: +.LFB1: + # ptwrite.c:26:1 + .loc 1 26 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 + pushq %rbx + .cfi_offset 3, -24 + movl %edi, -12(%rbp) + # ptwrite.c:27:3 + .loc 1 27 3 + movl -12(%rbp), %eax + movl %eax, %ebx +#APP +# 27 "ptwrite.c" 1 + PTWRITE %ebx; +# 0 "" 2 + # ptwrite.c:28:1 + .loc 1 28 1 +#NO_APP + nop + movq -8(%rbp), %rbx + leave + .cfi_def_cfa 7, 8 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE1: + .size ptwrite32, .-ptwrite32 + .globl main + .type main, @function +main: +.LFB2: + # ptwrite.c:32:1 + .loc 1 32 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:33:3 + .loc 1 33 3 + movl $66, %edi + call ptwrite64 + # ptwrite.c:34:3 + .loc 1 34 3 + movl $67, %edi + call ptwrite32 + # ptwrite.c:36:10 + .loc 1 36 10 + movl $0, %eax + # ptwrite.c:37:1 + .loc 1 37 1 + popq %rbp + .cfi_def_cfa 7, 8 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE2: + .size main, .-main +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0xa7 # 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 .LASF1 # DW_AT_producer: "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -mtune=generic -march=x86-64 -g" + .byte 0xc # DW_AT_language + .long .LASF2 # DW_AT_name: "ptwrite.c" + .long .LASF3 # DW_AT_comp_dir: "/root/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_subprogram) + # DW_AT_external + .long .LASF4 # DW_AT_name: "main" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x1f # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .long 0x4b # DW_AT_type + .quad .LFB2 # DW_AT_low_pc + .quad .LFE2-.LFB2 # 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 0x3 # (DIE (0x4b) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .ascii "int\0" # DW_AT_name + .uleb128 0x4 # (DIE (0x52) DW_TAG_subprogram) + # DW_AT_external + .long .LASF5 # DW_AT_name: "ptwrite32" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x19 # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .quad .LFB1 # DW_AT_low_pc + .quad .LFE1-.LFB1 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .long 0x80 # DW_AT_sibling + .uleb128 0x5 # (DIE (0x70) DW_TAG_formal_parameter) + .long .LASF0 # DW_AT_name: "value" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x19 # DW_AT_decl_line + .byte 0x10 # DW_AT_decl_column + .long 0x4b # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -28 + .byte 0 # end of children of DIE 0x52 + .uleb128 0x6 # (DIE (0x80) DW_TAG_subprogram) + # DW_AT_external + .long .LASF6 # DW_AT_name: "ptwrite64" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x13 # DW_AT_decl_line + .byte 0x1 # DW_AT_decl_column + # DW_AT_prototyped + .quad .LFB0 # DW_AT_low_pc + .quad .LFE0-.LFB0 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .uleb128 0x5 # (DIE (0x9a) DW_TAG_formal_parameter) + .long .LASF0 # DW_AT_name: "value" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x13 # DW_AT_decl_line + .byte 0x10 # DW_AT_decl_column + .long 0x4b # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -28 + .byte 0 # end of children of DIE 0x80 + .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 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 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 0x8 # (DW_FORM_string) + .byte 0 + .byte 0 + .uleb128 0x4 # (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 0x5 # (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 0x6 # (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) + .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 +.LASF3: + .string "/root/gdb/gdb/testsuite/gdb.btrace" +.LASF6: + .string "ptwrite64" +.LASF0: + .string "value" +.LASF1: + .string "GNU C17 10.3.1 20210422 (Red Hat 10.3.1-1) -mtune=generic -march=x86-64 -g" +.LASF5: + .string "ptwrite32" +.LASF2: + .string "ptwrite.c" +.LASF4: + .string "main" + .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 4bc5f4f144c..e9317467390 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -3661,6 +3661,80 @@ gdb_caching_proc skip_btrace_pt_tests { return $skip_btrace_tests } +# Run a test on the target to see if it supports ptwrite instructions and +# if GDB can decode ptwrite events. Return 0 if so, 1 if it does not. + +gdb_caching_proc skip_btrace_ptw_tests { + global srcdir subdir gdb_prompt inferior_exited_re decimal + + set me "skip_ptw_tests" + if { [skip_btrace_pt_tests] } { + verbose "$me: target does not support btrace, returning 1" 2 + return 1 + } + + 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 skip_ptw_tests 2 + gdb_test_multiple "next" "$me: next" { + -re -wrap ".*Illegal instruction.*" { + verbose -log "$me: ptwrite instruction support not detected." + set skip_ptw_tests 2 + } + -re -wrap ".*$inferior_exited_re normally.*" { + verbose -log "$me: ptwrite support not detected." + set skip_ptw_tests 2 + } + -re -wrap "$decimal.*(at|in).*" { + set skip_ptw_tests 1 + } + } + + if { $skip_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 skip_ptw_tests 0 + } + -re ".*${gdb_prompt} $" { + verbose -log "$me: ptwrite decoding support not detected." + } + } + } + + gdb_exit + remote_file build delete $obj + + verbose "$me: returning $skip_ptw_tests" 2 + return $skip_ptw_tests +} + + # Run a test on the target to see if it supports Aarch64 SVE hardware. # Return 0 if so, 1 if it does not. Note this causes a restart of GDB. diff --git a/gdbsupport/common.m4 b/gdbsupport/common.m4 index d3e9ecbe823..aebf484b515 100644 --- a/gdbsupport/common.m4 +++ b/gdbsupport/common.m4 @@ -179,6 +179,8 @@ AC_DEFUN([GDB_AC_COMMON], [ AC_CHECK_FUNCS(pt_insn_event) AC_CHECK_MEMBERS([struct pt_insn.enabled, struct pt_insn.resynced], [], [], [#include ]) + AC_CHECK_MEMBERS([struct pt_event.variant.ptwrite], [], [], + [#include ]) LIBS=$save_LIBS fi fi diff --git a/gdbsupport/config.in b/gdbsupport/config.in index a7ae23b4984..3d5543cb7b5 100644 --- a/gdbsupport/config.in +++ b/gdbsupport/config.in @@ -232,6 +232,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H +/* Define to 1 if `variant.ptwrite' is a member of `struct pt_event'. */ +#undef HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE + /* Define to 1 if `enabled' is a member of `struct pt_insn'. */ #undef HAVE_STRUCT_PT_INSN_ENABLED diff --git a/gdbsupport/configure b/gdbsupport/configure index 618f487749f..1f4f3ff02a5 100755 --- a/gdbsupport/configure +++ b/gdbsupport/configure @@ -9604,6 +9604,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 +" +if test "x$ac_cv_member_struct_pt_event_variant_ptwrite" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_PT_EVENT_VARIANT_PTWRITE 1 +_ACEOF + + fi LIBS=$save_LIBS -- 2.34.3 Intel Deutschland GmbH Registered Address: Am Campeon 10, 85579 Neubiberg, Germany Tel: +49 89 99 8853-0, 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