From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by sourceware.org (Postfix) with ESMTPS id C5C2439878CE for ; Wed, 16 Jun 2021 07:46:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C5C2439878CE IronPort-SDR: A1LeUVM7naFxvjd5qe1ZbubPhe0oerZp+0gr6xJLtdb/aQMy6ECTY0+pWqCeOGIJOubTysvpci MhEOfojr4nSQ== X-IronPort-AV: E=McAfee;i="6200,9189,10016"; a="185824688" X-IronPort-AV: E=Sophos;i="5.83,277,1616482800"; d="scan'208";a="185824688" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jun 2021 00:46:48 -0700 IronPort-SDR: 6gOSnMnAu+DvTMoTM+FMMczCfqhpXDZKxVSJcmEEPyY4dEf3mnXyQGs+znV5CMJhh5MW6UWs66 TkhEXEAZdJ3w== X-IronPort-AV: E=Sophos;i="5.83,277,1616482800"; d="scan'208";a="484786355" Received: from mulvlfelix.iul.intel.com (HELO localhost) ([172.28.48.31]) by orsmga001-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jun 2021 00:46:47 -0700 From: Felix Willgerodt To: markus.t.metzger@intel.com, gdb-patches@sourceware.org Subject: [PATCH v3 12/12] btrace: Extend ptwrite event decoding. Date: Wed, 16 Jun 2021 09:42:05 +0200 Message-Id: <20210616074205.1129553-13-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20210616074205.1129553-1-felix.willgerodt@intel.com> References: <20210616074205.1129553-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.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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, 16 Jun 2021 07:46:54 -0000 Call the ptwrite listener 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/ChangeLog: 2021-06-14 Felix Willgerodt * btrace.c (handle_pt_insn_events): Handle ptev_ptwrite. gdb/testsuite/ChangeLog: 2021-06-14 Felix Willgerodt * gdb.btrace/ptwrite.c: New file. * gdb.btrace/ptwrite.exp: New file. * gdb.btrace/x86_64-ptwrite.S: New file. * lib/gdb.exp (skip_btrace_ptw_tests): New function. gdb/doc/ChangeLog: 2021-06-14 Felix Willgerodt * python.texi (gdb.ptwrite): New documentation. --- gdb/NEWS | 6 + gdb/btrace.c | 52 +++ gdb/doc/python.texi | 134 ++++++ gdb/testsuite/gdb.btrace/ptwrite.c | 39 ++ gdb/testsuite/gdb.btrace/ptwrite.exp | 194 +++++++++ gdb/testsuite/gdb.btrace/x86_64-ptwrite.S | 479 ++++++++++++++++++++++ gdb/testsuite/lib/gdb.exp | 82 ++++ 7 files changed, 986 insertions(+) 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 56743fc9aea..c920a5cb8ec 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,12 @@ *** Changes since GDB 10 +* 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 listener function in Python. By default, the raw ptwrite + payload is printed for each ptwrite that is encountered. + * The 'set disassembler-options' command now supports specifying options for the ARC target. diff --git a/gdb/btrace.c b/gdb/btrace.c index d66c3e21f11..d276de723c0 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -1247,6 +1247,58 @@ handle_pt_insn_events (struct btrace_thread_info *btinfo, bfun->insn_offset - 1, offset); break; + + case ptev_ptwrite: + { + uint64_t *ip = nullptr; + gdb::unique_xmalloc_ptr ptw_string = nullptr; + struct btrace_insn ptw_insn; + btrace_insn_flags flags; + + /* Lookup the ip if available. */ + if (event.ip_suppressed == 0) + ip = &event.variant.ptwrite.ip; + else if (!btinfo->functions.empty () + && !btinfo->functions.back ().insn.empty ()) + ip = &btinfo->functions.back ().insn.back ().pc; + + if (btinfo->ptw_callback_fun != nullptr) + ptw_string = btinfo->ptw_callback_fun ( + &event.variant.ptwrite.payload, ip, + btinfo->ptw_listener); + + if (ptw_string == nullptr) + break; + + btinfo->aux_data.emplace_back (ptw_string.get ()); + + if (!btinfo->functions.empty () + && !btinfo->functions.back ().insn.empty ()) + flags = btinfo->functions.back ().insn.back ().flags; + else + flags = 0; + + /* Update insn list with ptw payload insn. */ + ptw_insn.aux_data_index = btinfo->aux_data.size () - 1; + ptw_insn.flags = flags; + ptw_insn.iclass = BTRACE_INSN_AUX; + ptw_insn.size = 0; + + if (ip != nullptr) + 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_PT_INSN_EVENT) */ diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index fa1c69a2283..3fe5b80e01b 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -6110,6 +6110,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 listener registration. @end menu @node gdb.printing @@ -6300,3 +6301,136 @@ 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} 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); +@} + +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 0x000000000040074c : ptwrite %rbx +13 [42] +14 0x0000000000400751 : 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_listener} as the ptwrite listener function. +This function will be called with the ptwrite payload and PC as arguments +during trace decoding. + +@findex gdb.ptwrite.register_listener +@defun register_listener (@var{listener}) +Used to register the ptwrite listener. The listener can be any callable +object that accepts two arguments. 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_listener +@defun get_listener () +Returns the currently active ptwrite listener function. +@end defun + +@findex gdb.ptwrite.default_listener +@defun default_listener (@var{payload}, @var{ip}) +The listener function active by default. +@end defun + +@value{GDBN} creates a new copy of the listener function for each thread to +allow for independent internal states. There is no support for registering +different listeners for different threads. The listener 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_listener(object): +... def __init__(self): +... self.var = 0 +... def __call__(self, payload, ip): +... if gdb.selected_thread().global_num == 1: +... self.var += 1 +... return "counter: @{@}, ip: @{:#x@}".format(self.var, ip) +... else: +... return None +... +>>> import gdb.ptwrite +>>> gdb.ptwrite.register_listener(my_listener()) +>>> +(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] +(gdb) info threads +* 1 Thread 0x7ffff7fd8740 (LWP 25796) "ptwrite_threads" task (arg=0x0) + at bin/ptwrite/ptwrite_threads.c:45 + 2 Thread 0x7ffff6eb8700 (LWP 25797) "ptwrite_threads" task (arg=0x0) + at bin/ptwrite/ptwrite_threads.c:45 +(gdb) thread 2 +[Switching to thread 2 (Thread 0x7ffff6eb8700 (LWP 25797))] +#0 task (arg=0x0) at ptwrite_threads.c:45 +45 return NULL; +(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/ptwrite.c b/gdb/testsuite/gdb.btrace/ptwrite.c new file mode 100644 index 00000000000..f5ead4e7d89 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/ptwrite.c @@ -0,0 +1,39 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2021 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +void +ptwrite64 (uint64_t value) +{ + asm volatile ("PTWRITE %0;" : : "b" (value)); +} + +void +ptwrite32 (uint32_t 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..2bbf0f41d3c --- /dev/null +++ b/gdb/testsuite/gdb.btrace/ptwrite.exp @@ -0,0 +1,194 @@ +# 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_pt_tests] } { + unsupported "Target does not support record btrace pt." + return -1 +} + +if { [skip_btrace_ptw_tests] } { + unsupported "Hardware does not support ptwrite instructions." + return -1 +} + +# Test libipt version (must be >= 2.0.0). +if {[require_libipt_version 2 0 0]} { + unsupported "Libipt doesn't support 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 +} else { + if {[is_amd64_regs_target]} { + standard_testfile x86_64-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" "Default: set unlimited" +gdb_test_no_output "record btrace pt" "Default: record btrace pt" +gdb_test "next" ".*" "Default: first next" +gdb_test "next" ".*" "Default: second next" + +# 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\\\].*" \ + ] "Default: record instruction-history 1" + +gdb_test "record instruction-history /a 1" [multi_line \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+.*" \ + ] "Default: record instruction-history /a 1" + +# 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\\\]" \ + ] "Default: record function-call-history 1,4" + +gdb_test "record function-call-history /a 1,4" [multi_line \ + "1\tmain" \ + "2\tptwrite64" \ + "3\tmain" \ + "4\tptwrite32" \ + ] "Default: record function-call-history /a 1,4" + +# Test payload printing during stepping +gdb_test "record goto 10" "No such instruction\." +gdb_test "record goto 9" ".*ptwrite64.* at .*ptwrite.c:23.*" +gdb_test "stepi" ".*\\\[42\\\].*" +gdb_test "reverse-stepi" ".*\\\[42\\\].*" +gdb_test "continue" ".*\\\[42\\\].*\\\[43\\\].*" +gdb_test "reverse-continue" ".*\\\[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: print(insn)" "" \ + "end" [multi_line \ + ".*RecordAuxiliary.*" \ + ".*RecordAuxiliary.*" \ + ] + + +### 2. Test listener registration +### 2.1 Custom listener + +gdb_test_multiline "Custom: register listener in python" \ + "python" "" \ + "def my_listener(payload, ip):" "" \ + " if payload == 66:" "" \ + " return \"payload: {0}, ip: {1:#x}\".format(payload, ip)" "" \ + " else:" "" \ + " return None" "" \ + "import gdb.ptwrite" "" \ + "gdb.ptwrite.register_listener(my_listener)" "" \ + "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 :.*" \ + ] "Custom: record instruction-history 1" + +### 2.2 None as listener + +gdb_test_multiline "None: register listener in python" \ + "python" "" \ + "import gdb.ptwrite" "" \ + "gdb.ptwrite.register_listener(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 :.*" \ + ] "None: record instruction-history 1" + +### 2.3 Lambdas as listener + +gdb_test_multiline "Lambdas: register listener in python" \ + "python" "" \ + "import gdb.ptwrite" "" \ + "gdb.ptwrite.register_listener(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 listener + +gdb_test_multiline "Functors: register listener 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_listener(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..0411870eca4 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/x86_64-ptwrite.S @@ -0,0 +1,479 @@ +/* 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 . + + + This file has been generated using gcc version 8.1.1 20180502: + 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: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 + pushq %rbx + .cfi_offset 3, -24 + movq %rdi, -16(%rbp) + # ptwrite.c:23:3 + .loc 1 23 3 + movq -16(%rbp), %rax + movq %rax, %rbx +#APP +# 23 "ptwrite.c" 1 + PTWRITE %rbx; +# 0 "" 2 + # ptwrite.c:24:1 + .loc 1 24 1 +#NO_APP + nop + popq %rbx + popq %rbp + .cfi_def_cfa 7, 8 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE0: + .size ptwrite64, .-ptwrite64 + .globl ptwrite32 + .type ptwrite32, @function +ptwrite32: +.LFB1: + # 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 + pushq %rbx + .cfi_offset 3, -24 + movl %edi, -12(%rbp) + # ptwrite.c:29:3 + .loc 1 29 3 + movl -12(%rbp), %eax + movl %eax, %ebx +#APP +# 29 "ptwrite.c" 1 + PTWRITE %ebx; +# 0 "" 2 + # ptwrite.c:30:1 + .loc 1 30 1 +#NO_APP + nop + popq %rbx + popq %rbp + .cfi_def_cfa 7, 8 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE1: + .size ptwrite32, .-ptwrite32 + .globl main + .type main, @function +main: +.LFB2: + # 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:36:3 + .loc 1 36 3 + movl $66, %edi + call ptwrite64 + # ptwrite.c:37:3 + .loc 1 37 3 + movl $67, %edi + call ptwrite32 + # ptwrite.c:39:10 + .loc 1 39 10 + movl $0, %eax + # ptwrite.c:40:1 + .loc 1 40 1 + popq %rbp + .cfi_def_cfa 7, 8 +# SUCC: EXIT [always] + ret + .cfi_endproc +.LFE2: + .size main, .-main +.Letext0: + .file 2 "/usr/include/bits/types.h" + .file 3 "/usr/include/bits/stdint-uintn.h" + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0x10f # 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 .LASF13 # DW_AT_producer: "GNU C17 8.1.1 20180502 (Red Hat 8.1.1-1) -mtune=generic -march=x86-64 -g" + .byte 0xc # DW_AT_language + .long .LASF14 # DW_AT_name: "ptwrite.c" + .long .LASF15 # 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 0x1 # DW_AT_byte_size + .byte 0x8 # DW_AT_encoding + .long .LASF0 # DW_AT_name: "unsigned char" + .uleb128 0x2 # (DIE (0x34) DW_TAG_base_type) + .byte 0x2 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF1 # DW_AT_name: "short unsigned int" + .uleb128 0x2 # (DIE (0x3b) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF2 # DW_AT_name: "unsigned int" + .uleb128 0x2 # (DIE (0x42) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF3 # DW_AT_name: "long unsigned int" + .uleb128 0x2 # (DIE (0x49) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x6 # DW_AT_encoding + .long .LASF4 # DW_AT_name: "signed char" + .uleb128 0x2 # (DIE (0x50) DW_TAG_base_type) + .byte 0x2 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF5 # DW_AT_name: "short int" + .uleb128 0x3 # (DIE (0x57) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .ascii "int\0" # DW_AT_name + .uleb128 0x4 # (DIE (0x5e) DW_TAG_typedef) + .long .LASF7 # DW_AT_name: "__uint32_t" + .byte 0x2 # DW_AT_decl_file (/usr/include/bits/types.h) + .byte 0x29 # DW_AT_decl_line + .byte 0x16 # DW_AT_decl_column + .long 0x3b # DW_AT_type + .uleb128 0x2 # (DIE (0x6a) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF6 # DW_AT_name: "long int" + .uleb128 0x4 # (DIE (0x71) DW_TAG_typedef) + .long .LASF8 # DW_AT_name: "__uint64_t" + .byte 0x2 # DW_AT_decl_file (/usr/include/bits/types.h) + .byte 0x2c # DW_AT_decl_line + .byte 0x1b # DW_AT_decl_column + .long 0x42 # DW_AT_type + .uleb128 0x2 # (DIE (0x7d) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x6 # DW_AT_encoding + .long .LASF9 # DW_AT_name: "char" + .uleb128 0x4 # (DIE (0x84) DW_TAG_typedef) + .long .LASF10 # DW_AT_name: "uint32_t" + .byte 0x3 # DW_AT_decl_file (/usr/include/bits/stdint-uintn.h) + .byte 0x1a # DW_AT_decl_line + .byte 0x14 # DW_AT_decl_column + .long 0x5e # DW_AT_type + .uleb128 0x4 # (DIE (0x90) DW_TAG_typedef) + .long .LASF11 # DW_AT_name: "uint64_t" + .byte 0x3 # DW_AT_decl_file (/usr/include/bits/stdint-uintn.h) + .byte 0x1b # DW_AT_decl_line + .byte 0x14 # DW_AT_decl_column + .long 0x71 # DW_AT_type + .uleb128 0x5 # (DIE (0x9c) DW_TAG_subprogram) + # DW_AT_external + .long .LASF16 # 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 0x57 # 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 0x6 # (DIE (0xba) DW_TAG_subprogram) + # DW_AT_external + .long .LASF17 # DW_AT_name: "ptwrite32" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x1b # 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 0xe8 # DW_AT_sibling + .uleb128 0x7 # (DIE (0xd8) DW_TAG_formal_parameter) + .long .LASF12 # DW_AT_name: "value" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x1b # DW_AT_decl_line + .byte 0x15 # DW_AT_decl_column + .long 0x84 # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -28 + .byte 0 # end of children of DIE 0xba + .uleb128 0x8 # (DIE (0xe8) DW_TAG_subprogram) + # DW_AT_external + .long .LASF18 # DW_AT_name: "ptwrite64" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x15 # 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 0x7 # (DIE (0x102) DW_TAG_formal_parameter) + .long .LASF12 # DW_AT_name: "value" + .byte 0x1 # DW_AT_decl_file (ptwrite.c) + .byte 0x15 # DW_AT_decl_line + .byte 0x15 # DW_AT_decl_column + .long 0x90 # DW_AT_type + .uleb128 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -32 + .byte 0 # end of children of DIE 0xe8 + .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 0xe # (DW_FORM_strp) + .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 0x16 # (TAG: DW_TAG_typedef) + .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) + .byte 0 + .byte 0 + .uleb128 0x5 # (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 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) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x7 # (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 0x8 # (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 +.LASF2: + .string "unsigned int" +.LASF7: + .string "__uint32_t" +.LASF15: + .string "gdb/gdb/testsuite/gdb.btrace" +.LASF14: + .string "ptwrite.c" +.LASF18: + .string "ptwrite64" +.LASF3: + .string "long unsigned int" +.LASF11: + .string "uint64_t" +.LASF0: + .string "unsigned char" +.LASF16: + .string "main" +.LASF10: + .string "uint32_t" +.LASF6: + .string "long int" +.LASF8: + .string "__uint64_t" +.LASF13: + .string "GNU C17 8.1.1 20180502 (Red Hat 8.1.1-1) -mtune=generic -march=x86-64 -g" +.LASF1: + .string "short unsigned int" +.LASF4: + .string "signed char" +.LASF12: + .string "value" +.LASF5: + .string "short int" +.LASF17: + .string "ptwrite32" +.LASF9: + .string "char" + .ident "GCC: (GNU) 8.1.1 20180502 (Red Hat 8.1.1-1)" + .section .note.GNU-stack,"",@progbits diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index a060b1767e5..8ac16f83849 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -3457,6 +3457,88 @@ gdb_caching_proc skip_btrace_pt_tests { return $skip_btrace_tests } +# Run a test on the target to see if it supports ptwrite instructions. +# Return 0 if so, 1 if it does not. Based on 'check_vmx_hw_available' +# from the GCC testsuite. + +gdb_caching_proc skip_btrace_ptw_tests { + global srcdir subdir gdb_prompt inferior_exited_re + set me "skip_ptw_tests" + + set src { + #include + #include + + bool + linux_supports_ptwrite () + { + static const char filename[] + = "/sys/bus/event_source/devices/intel_pt/caps/ptwrite"; + FILE *file = fopen (filename, "r"); + + if (file == NULL) + return false; + + int status, found = fscanf (file, "%d", &status); + fclose (file); + + if (found != 1) + return false; + + return status == 1; + } + + int + main () + { + if (linux_supports_ptwrite ()) + { + asm volatile("PTWRITE %0;" : : "b"(0x42)); + return 1; + }; + + return 0; + } + } + + if {![gdb_simple_compile $me $src executable]} { + return 1 + } + + # No error message, compilation succeeded so now run it via gdb. + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load "$obj" + gdb_run_cmd + + gdb_expect { + -re ".*Illegal instruction.*${gdb_prompt} $" { + verbose -log "$me: ptwrite support not detected." + set skip_ptw_tests 1 + } + -re ".*$inferior_exited_re normally.*${gdb_prompt} $" { + verbose -log "$me: ptwrite support not detected." + set skip_ptw_tests 1 + } + -re ".*exited with code 01.*${gdb_prompt} $" { + verbose -log "$me: ptwrite support detected." + set skip_ptw_tests 0 + } + default { + warning "\n$me: default case taken." + set skip_ptw_tests 1 + } + } + + 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 we have a minimum libipt version. # Return 0 if so, 1 if it does not. -- 2.25.4 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