From patchwork Wed May 29 08:47:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 32891 Received: (qmail 13405 invoked by alias); 29 May 2019 08:48:39 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 12545 invoked by uid 89); 29 May 2019 08:48:33 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT autolearn=ham version=3.3.1 spammy=Red, me, H*r:LOCAL X-HELO: mga01.intel.com Received: from mga01.intel.com (HELO mga01.intel.com) (192.55.52.88) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 29 May 2019 08:48:21 +0000 Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 29 May 2019 01:48:14 -0700 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by orsmga004.jf.intel.com with ESMTP; 29 May 2019 01:48:13 -0700 Received: from ulvlx001.iul.intel.com (ulvlx001.iul.intel.com [172.28.207.17]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id x4T8mCNN007678; Wed, 29 May 2019 09:48:12 +0100 Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id x4T8mCZL030833; Wed, 29 May 2019 10:48:12 +0200 Received: (from fwillger@localhost) by ulvlx001.iul.intel.com with LOCAL id x4T8mCug030829; Wed, 29 May 2019 10:48:12 +0200 From: felix.willgerodt@intel.com To: gdb-patches@sourceware.org Cc: markus.t.metzger@intel.com, Felix Willgerodt Subject: [PATCH 10/10] btrace: Extend event decoding for ptwrite. Date: Wed, 29 May 2019 10:47:53 +0200 Message-Id: <1559119673-30516-11-git-send-email-felix.willgerodt@intel.com> In-Reply-To: <1559119673-30516-1-git-send-email-felix.willgerodt@intel.com> References: <1559119673-30516-1-git-send-email-felix.willgerodt@intel.com> X-IsSubscribed: yes From: Felix Willgerodt 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. 2019-05-29 Felix Willgerodt gdb/ChangeLog: * btrace.c (handle_pt_insn_events): Handle ptev_ptwrite. gdb/testsuite/ChangeLog: * 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: * python.texi (gdb.ptwrite): New documentation. --- gdb/NEWS | 6 + gdb/btrace.c | 47 +++ gdb/doc/python.texi | 111 +++++ gdb/testsuite/gdb.btrace/ptwrite.c | 40 ++ gdb/testsuite/gdb.btrace/ptwrite.exp | 212 ++++++++++ gdb/testsuite/gdb.btrace/x86_64-ptwrite.S | 479 ++++++++++++++++++++++ gdb/testsuite/lib/gdb.exp | 92 +++++ 7 files changed, 987 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 6546b7243a9..1fca2f0cfd2 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,12 @@ *** Changes since GDB 8.3 +* 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. + * New built-in convenience variables $_gdb_major and $_gdb_minor provide the GDB version. They are handy for conditionally using features available only in or since specific GDB versions, in diff --git a/gdb/btrace.c b/gdb/btrace.c index 5bdef1c1768..e098abba514 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -1244,6 +1244,53 @@ 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; + + /* Lookup the ip. */ + 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; + else + /* This should never happen. */ + error (_("Failed to obtain the PC of the current instruction.")); + + try + { + if (btinfo->ptw_callback_fun != nullptr) + ptw_string = btinfo->ptw_callback_fun ( + &event.variant.ptwrite.payload, ip, + btinfo->ptw_listener); + } + catch (const gdb_exception_error &error) + { + warning (_("Failed to call ptwrite listener.")); + } + + if (ptw_string == nullptr) + break; + + btinfo->aux_data.emplace_back (ptw_string.get ()); + + /* Update insn list with ptw payload insn. */ + ptw_insn.aux_data_index = btinfo->aux_data.size () - 1; + ptw_insn.flags = 0; + ptw_insn.iclass = BTRACE_INSN_AUX; + ptw_insn.size = 0; + + bfun = ftrace_update_function (btinfo, *ip); + 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 e892caf9e18..8fb052c3b83 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -5683,6 +5683,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 @@ -5874,3 +5875,113 @@ substitute_prompt (``frame: \f, "frame: main, print arguments: 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 PTWRITE instruction. 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 'record instruction-history', +'record function-call-history' and all stepping commands and is accessible +in Python as a @code{RecordAuxiliary} object. + +@exdent Sample program: +@smallexample +void +ptwrite64 (unsigned long long value) +@{ + __builtin_ia32_ptwrite64 (value); +@} + +int +main (void) +@{ + ptwrite64 (0x42); + return 0; /* break here. */ +@} +@end smallexample + +@exdent @value{GDBN} output after recording the sample program in pt format: +@smallexample +(gdb) record instruction-history 12,14 +12 0x000000000040074c : ptwrite %rbx +13 [payload: 0x42] +14 0x0000000000400751 : mov -0x8(%rbp),%rbx +(gdb) record function-call-history +1 main +2 ptwrite64 + [payload: 0x42] +3 main +@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 @dfn{ptwrite listener function}. +This function will be called with the ptwrite payload and IP as arguments +during trace decoding. + +@table @code + +@item 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. + +@item get_listener () +Returns the currently active ptwrite listener function. + +@item default_listener (@var{payload}, @var{ip}) +The listener function active by default. +@end table + +When recording multithreaded programs, @value{GDBN} creates a new copy of the +listener function for each thread to allow for independent internal states. +There is currently 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} or similar. + +@exdent For example: +@smallexample +(gdb) python-interactive +>>> def my_listener(payload, ip): +... if gdb.selected_thread().global_num == 1: +... return "payload: @{0@}, ip: @{:#x@}".format(payload, ip) +... else: +... return None +... +>>> import gdb.ptwrite +>>> gdb.ptwrite.register_listener(my_listener) +>>> +(gdb) record instruction-history 127,129 +127 0x000000000040116c : ptwrite %ebx +128 [payload: 4919, ip: 0x40074c] +129 0x0000000000401170 : nop +(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 instruction-history 1753,1755 +1753 0x000000000040116c : ptwrite %ebx +1754 0x0000000000401170 : nop +1755 0x0000000000401171 : pop %rbx +@end smallexample + +This GDB 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..5e7ecb75e02 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/ptwrite.c @@ -0,0 +1,40 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2018 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..4cbd030be44 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/ptwrite.exp @@ -0,0 +1,212 @@ +# This testcase is part of GDB, the GNU debugger. +# +# Copyright 2018 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 +} + +set comp_flags "additional_flags=-I${srcdir}/.." +set opts {} + +if [info exists COMPILE] { + # make check RUNTESTFLAGS="gdb.btrace/ptwrite.exp COMPILE=1" + standard_testfile ptwrite.c + lappend opts debug comp_flags +} elseif {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} { + if {[is_amd64_regs_target]} { + standard_testfile x86_64-ptwrite.S + } else { + unsupported "target architecture not supported" + return -1 + } +} else { + unsupported "target architecture not supported" + return -1 +} + +if [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] { + unsupported "Compiler does not support ptwrite." + 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 libipt version (must be >= 2.0.0) +set libipt_supports_ptwrite 0 + +gdb_test_multiple "maint info btrace" "check libipt version" { + -re ".*Version: \[01\]\.\[0-9\]+\.\[0-9\]+.*" + { + set libipt_supports_ptwrite 0 + } + -re ".*Version: \[0-9\]+\.\[0-9\]+\.\[0-9\]+.*" + { + set libipt_supports_ptwrite 1 + } + default { + set libipt_supports_ptwrite 0 + } +} + +if { $libipt_supports_ptwrite == 0 } { + unsupported "libipt version doesn't support ptwrite decoding." + return -1 +} + +# Test record instruction-history +gdb_test "record instruction-history 1" [multi_line \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[payload: 0x42\\\]" \ + ".*\[0-9\]+\t $hex :\tptwrite %\[a-z\]+" \ + "\[0-9\]+\t \\\[payload: 0x43\\\].*" \ + ] "Default: record instruction-history 1" + +# Test function call history +gdb_test "record function-call-history 1,4" [multi_line \ + "1\tmain" \ + "2\tptwrite64" \ + "\t\t\\\[payload: 0x42\\\]" \ + "3\tmain" \ + "4\tptwrite32" \ + "\t\t\\\[payload: 0x43\\\]" \ + ] "Default: record function-call-history 1,4" + +gdb_test "record function-call-history /s 1,4" [multi_line \ + "1\tmain" \ + "2\tptwrite64" \ + "3\tmain" \ + "4\tptwrite32" \ + ] "Default: record function-call-history /s 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" ".*\\\[payload: 0x42\\\].*" +gdb_test "reverse-stepi" ".*\\\[payload: 0x42\\\].*" +gdb_test "continue" ".*\\\[payload: 0x42\\\].*\\\[payload: 0x43\\\].*" +gdb_test "reverse-continue" ".*\\\[payload: 0x43\\\].*\\\[payload: 0x42\\\].*" + +# Test auxiliary type in python +gdb_py_test_multiple "Default: 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_py_test_multiple "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_py_test_multiple "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_py_test_multiple "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_py_test_multiple "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..138ed17a42a --- /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 2018 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 c703a7e6338..ba7ccfd46ba 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -2874,6 +2874,98 @@ 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 up, compile, and execute a test program. + # Include the current process ID in the file names to prevent conflicts + # with invocations for multiple testsuites. + set src [standard_temp_file ptw[pid].c] + set exe [standard_temp_file ptw[pid].x] + + gdb_produce_source $src { + #include + #include + #include + #include "x86-cpuid.h" + + #define bit_PTW (1 << 4) + + bool + have_ptw () + { + unsigned int eax, ebx, ecx, edx; + + if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) + return false; + + if ((ecx & bit_OSXSAVE) != bit_OSXSAVE) + return false; + + if (__get_cpuid_max (0, NULL) < 0x14) + return false; + + __cpuid_count (0x14, 0, eax, ebx, ecx, edx); + + return (ebx & bit_PTW) == bit_PTW; + } + + int + main () + { + return have_ptw (); + } + + } + + verbose "$me: compiling testfile $src" 2 + + set test_flags [list additional_flags=-I${srcdir}/../nat] + + set compile_flags [concat {debug nowarnings quiet} ${test_flags}] + set lines [gdb_compile $src $exe executable $compile_flags] + + if ![string match "" $lines] then { + verbose "$me: testfile compilation failed, returning 1" 2 + file delete $src + return 1 + } + + # No error message, compilation succeeded so now run it via gdb. + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $exe + if ![runto_main] { + file delete $src + return 1 + } + file delete $src + + # In case of an unexpected output, we return 2 as a fail value. + set skip_ptw_tests 2 + gdb_test_multiple "print (int) have_ptw ()" "check ptw support" { + -re ".. = 1\r\n$gdb_prompt $" { + set skip_ptw_tests 0 + } + -re ".. = 0\r\n$gdb_prompt $" { + set skip_ptw_tests 1 + } + } + + gdb_exit + remote_file build delete $exe + + 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.