From patchwork Mon Mar 5 10:59:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Metzger, Markus T" X-Patchwork-Id: 26198 Received: (qmail 76592 invoked by alias); 5 Mar 2018 10:59:23 -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 76418 invoked by uid 89); 5 Mar 2018 10:59:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy= X-HELO: mga05.intel.com Received: from mga05.intel.com (HELO mga05.intel.com) (192.55.52.43) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 05 Mar 2018 10:59:18 +0000 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Mar 2018 02:59:17 -0800 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by fmsmga004.fm.intel.com with ESMTP; 05 Mar 2018 02:59:16 -0800 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 w25AxFER027632; Mon, 5 Mar 2018 10:59:15 GMT Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id w25AxFIj004931; Mon, 5 Mar 2018 11:59:15 +0100 Received: (from mmetzger@localhost) by ulvlx001.iul.intel.com with LOCAL id w25AxFd6004927; Mon, 5 Mar 2018 11:59:15 +0100 From: Markus Metzger To: gdb-patches@sourceware.org Subject: [PATCH v2 2/2] btrace: set/show record btrace cpu Date: Mon, 5 Mar 2018 11:59:15 +0100 Message-Id: <1520247555-4643-2-git-send-email-markus.t.metzger@intel.com> In-Reply-To: <1520247555-4643-1-git-send-email-markus.t.metzger@intel.com> References: <1520247555-4643-1-git-send-email-markus.t.metzger@intel.com> X-IsSubscribed: yes Add new set/show commands to set the processor that is used for enabling errata workarounds when decoding branch trace. The general format is ":" but we also allow two special values "auto" and "none". The default is "auto", which is the current behaviour of having GDB determine the processor on which the trace was recorded. If that cpu is not known to the trace decoder, e.g. when using an old decoder on a new system, decode may fail with "unknown cpu". In most cases it should suffice to 'downgrade' decode to assume an older cpu. Unfortunately, we can't do this automatically. The other special value, "none", disables errata workarounds. 2018-03-05 Markus Metzger gdb/ * NEWS (New options): announce set/show record btrace cpu. * btrace.c: Include record-btrace.h. (btrace_compute_ftrace_pt): Skip enabling errata workarounds if the vendor is unknown. (btrace_compute_ftrace_1): Add cpu parameter. Update callers. Maybe overwrite the btrace configuration's cpu. (btrace_compute_ftrace): Add cpu parameter. Update callers. (btrace_fetch): Add cpu parameter. Update callers. (btrace_maint_update_pt_packets): Call record_btrace_get_cpu. Maybe overwrite the btrace configuration's cpu. Skip enabling errata workarounds if the vendor is unknown. * python/py-record-btrace.c: Include record-btrace.h. (recpy_bt_begin, recpy_bt_end, recpy_bt_instruction_history) (recpy_bt_function_call_history): Call record_btrace_get_cpu. * record-btrace.c (record_btrace_cpu_state_kind): New. (record_btrace_cpu): New. (set_record_btrace_cpu_cmdlist): New. (record_btrace_get_cpu): New. (require_btrace_thread, record_btrace_info) (record_btrace_resume_thread): Call record_btrace_get_cpu. (cmd_set_record_btrace_cpu_none): New. (cmd_set_record_btrace_cpu_auto): New. (cmd_set_record_btrace_cpu): New. (cmd_show_record_btrace_cpu): New. (_initialize_record_btrace): Initialize set/show record btrace cpu commands. * record-btrace.h (record_btrace_get_cpu): New. testsuite/ * gdb.btrace/cpu.exp: New. doc/ * gdb.texinfo: Document set/show record btrace cpu. --- gdb/NEWS | 5 ++ gdb/btrace.c | 72 +++++++++++----- gdb/btrace.h | 6 +- gdb/doc/gdb.texinfo | 63 ++++++++++++++ gdb/python/py-record-btrace.c | 9 +- gdb/record-btrace.c | 177 ++++++++++++++++++++++++++++++++++++++- gdb/record-btrace.h | 4 + gdb/testsuite/gdb.btrace/cpu.exp | 76 +++++++++++++++++ 8 files changed, 379 insertions(+), 33 deletions(-) create mode 100644 gdb/testsuite/gdb.btrace/cpu.exp diff --git a/gdb/NEWS b/gdb/NEWS index 867e268..7815ad8 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -12,6 +12,11 @@ set debug fbsd-nat show debug fbsd-nat Control display of debugging info regarding the FreeBSD native target. +set record btrace cpu +show record btrace cpu + Controls the processor to be used for enabling errata workarounds for branch + trace decode. + *** Changes in GDB 8.1 * GDB now supports dynamically creating arbitrary register groups specified diff --git a/gdb/btrace.c b/gdb/btrace.c index 158d03c..269ee51 100644 --- a/gdb/btrace.c +++ b/gdb/btrace.c @@ -35,6 +35,9 @@ #include "gdbcmd.h" #include "cli/cli-utils.h" +/* For maintenance commands. */ +#include "record-btrace.h" + #include #include #include @@ -1428,15 +1431,20 @@ btrace_compute_ftrace_pt (struct thread_info *tp, config.begin = btrace->data; config.end = btrace->data + btrace->size; - config.cpu.vendor = pt_translate_cpu_vendor (btrace->config.cpu.vendor); - config.cpu.family = btrace->config.cpu.family; - config.cpu.model = btrace->config.cpu.model; - config.cpu.stepping = btrace->config.cpu.stepping; + /* We treat an unknown vendor as 'no errata'. */ + if (btrace->config.cpu.vendor != CV_UNKNOWN) + { + config.cpu.vendor + = pt_translate_cpu_vendor (btrace->config.cpu.vendor); + config.cpu.family = btrace->config.cpu.family; + config.cpu.model = btrace->config.cpu.model; + config.cpu.stepping = btrace->config.cpu.stepping; - errcode = pt_cpu_errata (&config.errata, &config.cpu); - if (errcode < 0) - error (_("Failed to configure the Intel Processor Trace decoder: %s."), - pt_errstr (pt_errcode (errcode))); + errcode = pt_cpu_errata (&config.errata, &config.cpu); + if (errcode < 0) + error (_("Failed to configure the Intel Processor Trace " + "decoder: %s."), pt_errstr (pt_errcode (errcode))); + } decoder = pt_insn_alloc_decoder (&config); if (decoder == NULL) @@ -1485,10 +1493,14 @@ btrace_compute_ftrace_pt (struct thread_info *tp, #endif /* defined (HAVE_LIBIPT) */ /* Compute the function branch trace from a block branch trace BTRACE for - a thread given by BTINFO. */ + a thread given by BTINFO. If CPU is not NULL, overwrite the cpu in the + branch trace configuration. This is currently only used for the PT + format. */ static void -btrace_compute_ftrace_1 (struct thread_info *tp, struct btrace_data *btrace, +btrace_compute_ftrace_1 (struct thread_info *tp, + struct btrace_data *btrace, + const struct btrace_cpu *cpu, std::vector &gaps) { DEBUG ("compute ftrace"); @@ -1503,6 +1515,10 @@ btrace_compute_ftrace_1 (struct thread_info *tp, struct btrace_data *btrace, return; case BTRACE_FORMAT_PT: + /* Overwrite the cpu we use for enabling errata workarounds. */ + if (cpu != nullptr) + btrace->variant.pt.config.cpu = *cpu; + btrace_compute_ftrace_pt (tp, &btrace->variant.pt, gaps); return; } @@ -1521,13 +1537,14 @@ btrace_finalize_ftrace (struct thread_info *tp, std::vector &gaps) } static void -btrace_compute_ftrace (struct thread_info *tp, struct btrace_data *btrace) +btrace_compute_ftrace (struct thread_info *tp, struct btrace_data *btrace, + const struct btrace_cpu *cpu) { std::vector gaps; TRY { - btrace_compute_ftrace_1 (tp, btrace, gaps); + btrace_compute_ftrace_1 (tp, btrace, cpu, gaps); } CATCH (error, RETURN_MASK_ALL) { @@ -1564,7 +1581,7 @@ btrace_add_pc (struct thread_info *tp) block->begin = pc; block->end = pc; - btrace_compute_ftrace (tp, &btrace); + btrace_compute_ftrace (tp, &btrace, NULL); do_cleanups (cleanup); } @@ -1872,7 +1889,7 @@ btrace_decode_error (enum btrace_format format, int errcode) /* See btrace.h. */ void -btrace_fetch (struct thread_info *tp) +btrace_fetch (struct thread_info *tp, const struct btrace_cpu *cpu) { struct btrace_thread_info *btinfo; struct btrace_target_info *tinfo; @@ -1948,7 +1965,7 @@ btrace_fetch (struct thread_info *tp) btrace_maint_clear (btinfo); btrace_clear_history (btinfo); - btrace_compute_ftrace (tp, &btrace); + btrace_compute_ftrace (tp, &btrace, cpu); } do_cleanups (cleanup); @@ -3028,6 +3045,7 @@ static void btrace_maint_update_pt_packets (struct btrace_thread_info *btinfo) { struct pt_packet_decoder *decoder; + const struct btrace_cpu *cpu; struct btrace_data_pt *pt; struct pt_config config; int errcode; @@ -3044,15 +3062,23 @@ btrace_maint_update_pt_packets (struct btrace_thread_info *btinfo) config.begin = pt->data; config.end = pt->data + pt->size; - config.cpu.vendor = pt_translate_cpu_vendor (pt->config.cpu.vendor); - config.cpu.family = pt->config.cpu.family; - config.cpu.model = pt->config.cpu.model; - config.cpu.stepping = pt->config.cpu.stepping; + cpu = record_btrace_get_cpu (); + if (cpu == nullptr) + cpu = &pt->config.cpu; + + /* We treat an unknown vendor as 'no errata'. */ + if (cpu->vendor != CV_UNKNOWN) + { + config.cpu.vendor = pt_translate_cpu_vendor (cpu->vendor); + config.cpu.family = cpu->family; + config.cpu.model = cpu->model; + config.cpu.stepping = cpu->stepping; - errcode = pt_cpu_errata (&config.errata, &config.cpu); - if (errcode < 0) - error (_("Failed to configure the Intel Processor Trace decoder: %s."), - pt_errstr (pt_errcode (errcode))); + errcode = pt_cpu_errata (&config.errata, &config.cpu); + if (errcode < 0) + error (_("Failed to configure the Intel Processor Trace " + "decoder: %s."), pt_errstr (pt_errcode (errcode))); + } decoder = pt_pkt_alloc_decoder (&config); if (decoder == NULL) diff --git a/gdb/btrace.h b/gdb/btrace.h index 5c3f21b..4d57edb 100644 --- a/gdb/btrace.h +++ b/gdb/btrace.h @@ -385,8 +385,10 @@ extern void btrace_teardown (struct thread_info *); extern const char *btrace_decode_error (enum btrace_format format, int errcode); -/* Fetch the branch trace for a single thread. */ -extern void btrace_fetch (struct thread_info *); +/* Fetch the branch trace for a single thread. If CPU is not NULL, assume + CPU for trace decode. */ +extern void btrace_fetch (struct thread_info *, + const struct btrace_cpu *cpu); /* Clear the branch trace for a single thread. */ extern void btrace_clear (struct thread_info *); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 74e0fdb..4592455 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -6952,10 +6952,73 @@ and to read-write memory. Beware that the accessed memory corresponds to the live target and not necessarily to the current replay position. +@item set record btrace cpu @var{identifier} +Set the processor to be used for enabling workarounds for processor +errata when decoding the trace. + +Processor errata are defects in processor operation, caused by its +design or manufacture. They can cause a trace not to match the +specification. This, in turn, may cause trace decode to fail. +@value{GDBN} can detect erroneous trace packets and correct them, thus +avoiding the decoding failures. These corrections are known as +@dfn{errata workarounds}, and are enabled based on the processor on +which the trace was recorded. + +By default, @value{GDBN} attempts to detect the processor +automatically, and apply the necessary workarounds for it. However, +you may need to specify the processor if @value{GDBN} does not yet +support it. This command allows you to do that, and also allows to +disable the workarounds. + +The argument @var{identifier} identifies the @sc{cpu} and is of the +form: @code{@var{vendor}:@var{procesor identifier}}. In addition, +there are two special identifiers, @code{none} and @code{auto} +(default). + +The following vendor identifiers and corresponding processor +identifiers are currently supported: + +@multitable @columnfractions .1 .9 + +@item @code{intel} +@tab @var{family}/@var{model}[/@var{stepping}] + +@end multitable + +On GNU/Linux systems, the processor @var{family}, @var{model}, and +@var{stepping} can be obtained from @code{/proc/cpuinfo}. + +If @var{identifier} is @code{auto}, enable errata workarounds for the +processor on which the trace was recorded. If @var{identifier} is +@code{none}, errata workarounds are disabled. + +For example, when using an old @value{GDBN} on a new system, decode +may fail because @value{GDBN} does not support the new processor. It +often suffices to specify an older processor that @value{GDBN} +supports. + +@smallexample +(gdb) info record +Active record target: record-btrace +Recording format: Intel Processor Trace. +Buffer size: 16kB. +Failed to configure the Intel Processor Trace decoder: unknown cpu. +(gdb) set record btrace cpu intel:6/158 +(gdb) info record +Active record target: record-btrace +Recording format: Intel Processor Trace. +Buffer size: 16kB. +Recorded 84872 instructions in 3189 functions (0 gaps) for thread 1 (...). +@end smallexample + @kindex show record btrace @item show record btrace replay-memory-access Show the current setting of @code{replay-memory-access}. +@item show record btrace cpu +Show the processor to be used for enabling trace decode errata +workarounds. + @kindex set record btrace bts @item set record btrace bts buffer-size @var{size} @itemx set record btrace bts buffer-size unlimited diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c index 35828a6..d78df7f 100644 --- a/gdb/python/py-record-btrace.c +++ b/gdb/python/py-record-btrace.c @@ -24,6 +24,7 @@ #include "btrace.h" #include "py-record.h" #include "py-record-btrace.h" +#include "record-btrace.h" #include "disasm.h" #if defined (IS_PY3K) @@ -678,7 +679,7 @@ recpy_bt_begin (PyObject *self, void *closure) if (tinfo == NULL) Py_RETURN_NONE; - btrace_fetch (tinfo); + btrace_fetch (tinfo, record_btrace_get_cpu ()); if (btrace_is_empty (tinfo)) Py_RETURN_NONE; @@ -700,7 +701,7 @@ recpy_bt_end (PyObject *self, void *closure) if (tinfo == NULL) Py_RETURN_NONE; - btrace_fetch (tinfo); + btrace_fetch (tinfo, record_btrace_get_cpu ()); if (btrace_is_empty (tinfo)) Py_RETURN_NONE; @@ -724,7 +725,7 @@ recpy_bt_instruction_history (PyObject *self, void *closure) if (tinfo == NULL) Py_RETURN_NONE; - btrace_fetch (tinfo); + btrace_fetch (tinfo, record_btrace_get_cpu ()); if (btrace_is_empty (tinfo)) Py_RETURN_NONE; @@ -753,7 +754,7 @@ recpy_bt_function_call_history (PyObject *self, void *closure) if (tinfo == NULL) Py_RETURN_NONE; - btrace_fetch (tinfo); + btrace_fetch (tinfo, record_btrace_get_cpu ()); if (btrace_is_empty (tinfo)) Py_RETURN_NONE; diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 905f0c4..8205e97 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -60,6 +60,20 @@ static const char *const replay_memory_access_types[] = /* The currently allowed replay memory access type. */ static const char *replay_memory_access = replay_memory_access_read_only; +/* The cpu state kinds. */ +enum record_btrace_cpu_state_kind +{ + CS_AUTO, + CS_NONE, + CS_CPU +}; + +/* The current cpu state. */ +static enum record_btrace_cpu_state_kind record_btrace_cpu_state = CS_AUTO; + +/* The current cpu for trace decode. */ +static struct btrace_cpu record_btrace_cpu; + /* Command lists for "set/show record btrace". */ static struct cmd_list_element *set_record_btrace_cmdlist; static struct cmd_list_element *show_record_btrace_cmdlist; @@ -87,6 +101,9 @@ static struct cmd_list_element *show_record_btrace_bts_cmdlist; static struct cmd_list_element *set_record_btrace_pt_cmdlist; static struct cmd_list_element *show_record_btrace_pt_cmdlist; +/* Command list for "set record btrace cpu". */ +static struct cmd_list_element *set_record_btrace_cpu_cmdlist; + /* Print a record-btrace debug message. Use do ... while (0) to avoid ambiguities when used in if statements. */ @@ -100,6 +117,26 @@ static struct cmd_list_element *show_record_btrace_pt_cmdlist; while (0) +/* Return the cpu configured by the user. Returns NULL if the cpu was + configured as auto. */ +const struct btrace_cpu * +record_btrace_get_cpu (void) +{ + switch (record_btrace_cpu_state) + { + case CS_AUTO: + return nullptr; + + case CS_NONE: + record_btrace_cpu.vendor = CV_UNKNOWN; + /* Fall through. */ + case CS_CPU: + return &record_btrace_cpu; + } + + error (_("Internal error: bad record btrace cpu state.")); +} + /* Update the branch trace for the current thread and return a pointer to its thread_info. @@ -119,7 +156,7 @@ require_btrace_thread (void) validate_registers_access (); - btrace_fetch (tp); + btrace_fetch (tp, record_btrace_get_cpu ()); if (btrace_is_empty (tp)) error (_("No trace.")); @@ -427,7 +464,7 @@ record_btrace_info (struct target_ops *self) if (conf != NULL) record_btrace_print_conf (conf); - btrace_fetch (tp); + btrace_fetch (tp, record_btrace_get_cpu ()); insns = 0; calls = 0; @@ -1841,7 +1878,7 @@ record_btrace_resume_thread (struct thread_info *tp, btinfo = &tp->btrace; /* Fetch the latest branch trace. */ - btrace_fetch (tp); + btrace_fetch (tp, record_btrace_get_cpu ()); /* A resume request overwrites a preceding resume or stop request. */ btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP); @@ -2977,7 +3014,113 @@ cmd_show_replay_memory_access (struct ui_file *file, int from_tty, replay_memory_access); } -/* The "set record btrace bts" command. */ +/* The "set record btrace cpu none" command. */ + +static void +cmd_set_record_btrace_cpu_none (const char *args, int from_tty) +{ + if (args != nullptr && *args != 0) + error (_("Trailing junk: '%s'."), args); + + record_btrace_cpu_state = CS_NONE; +} + +/* The "set record btrace cpu auto" command. */ + +static void +cmd_set_record_btrace_cpu_auto (const char *args, int from_tty) +{ + if (args != nullptr && *args != 0) + error (_("Trailing junk: '%s'."), args); + + record_btrace_cpu_state = CS_AUTO; +} + +/* The "set record btrace cpu" command. */ + +static void +cmd_set_record_btrace_cpu (const char *args, int from_tty) +{ + if (args == nullptr) + args = ""; + + /* We use a hard-coded vendor string for now. */ + unsigned int family, model, stepping; + int l1, l2, matches = sscanf (args, "intel: %u/%u%n/%u%n", &family, + &model, &l1, &stepping, &l2); + if (matches == 3) + { + if (strlen (args) != l2) + error (_("Trailing junk: '%s'."), args + l2); + } + else if (matches == 2) + { + if (strlen (args) != l1) + error (_("Trailing junk: '%s'."), args + l1); + + stepping = 0; + } + else + error (_("Bad format. See \"help set record btrace cpu\".")); + + if (USHRT_MAX < family) + error (_("Cpu family too big.")); + + if (UCHAR_MAX < model) + error (_("Cpu model too big.")); + + if (UCHAR_MAX < stepping) + error (_("Cpu stepping too big.")); + + record_btrace_cpu.vendor = CV_INTEL; + record_btrace_cpu.family = family; + record_btrace_cpu.model = model; + record_btrace_cpu.stepping = stepping; + + record_btrace_cpu_state = CS_CPU; +} + +/* The "show record btrace cpu" command. */ + +static void +cmd_show_record_btrace_cpu (const char *args, int from_tty) +{ + const char *cpu; + + if (args != nullptr && *args != 0) + error (_("Trailing junk: '%s'."), args); + + switch (record_btrace_cpu_state) + { + case CS_AUTO: + printf_unfiltered (_("btrace cpu is 'auto'.\n")); + return; + + case CS_NONE: + printf_unfiltered (_("btrace cpu is 'none'.\n")); + return; + + case CS_CPU: + switch (record_btrace_cpu.vendor) + { + case CV_INTEL: + if (record_btrace_cpu.stepping == 0) + printf_unfiltered (_("btrace cpu is 'intel: %u/%u'.\n"), + record_btrace_cpu.family, + record_btrace_cpu.model); + else + printf_unfiltered (_("btrace cpu is 'intel: %u/%u/%u'.\n"), + record_btrace_cpu.family, + record_btrace_cpu.model, + record_btrace_cpu.stepping); + return; + } + } + + error (_("Internal error: bad cpu state.")); +} + +/* The "s record btrace bts" command. */ static void cmd_set_record_btrace_bts (const char *args, int from_tty) @@ -3085,6 +3228,32 @@ replay."), &set_record_btrace_cmdlist, &show_record_btrace_cmdlist); + add_prefix_cmd ("cpu", class_support, cmd_set_record_btrace_cpu, + _("\ +Set the cpu to be used for trace decode.\n\n\ +The format is \":\" or \"none\" or \"auto\" (default).\n\ +For vendor \"intel\" the format is \"/[/]\".\n\n\ +When decoding branch trace, enable errata workarounds for the specified cpu.\n\ +The default is \"auto\", which uses the cpu on which the trace was recorded.\n\ +When GDB does not support that cpu, this option can be used to enable\n\ +workarounds for a similar cpu that GDB supports.\n\n\ +When set to \"none\", errata workarounds are disabled."), + &set_record_btrace_cpu_cmdlist, + _("set record btrace cpu "), 1, + &set_record_btrace_cmdlist); + + add_cmd ("auto", class_support, cmd_set_record_btrace_cpu_auto, _("\ +Automatically determine the cpu to be used for trace decode."), + &set_record_btrace_cpu_cmdlist); + + add_cmd ("none", class_support, cmd_set_record_btrace_cpu_none, _("\ +Do not enable errata workarounds for trace decode."), + &set_record_btrace_cpu_cmdlist); + + add_cmd ("cpu", class_support, cmd_show_record_btrace_cpu, _("\ +Show the cpu to be used for trace decode."), + &show_record_btrace_cmdlist); + add_prefix_cmd ("bts", class_support, cmd_set_record_btrace_bts, _("Set record btrace bts options"), &set_record_btrace_bts_cmdlist, diff --git a/gdb/record-btrace.h b/gdb/record-btrace.h index ba66719..e17b643 100644 --- a/gdb/record-btrace.h +++ b/gdb/record-btrace.h @@ -25,4 +25,8 @@ /* Push the record_btrace target. */ extern void record_btrace_push_target (void); +/* Return the cpu configured by the user via "set btrace cpu". Returns + NULL if the cpu was configured as auto. */ +extern const struct btrace_cpu *record_btrace_get_cpu (void); + #endif /* RECORD_BTRACE_H */ diff --git a/gdb/testsuite/gdb.btrace/cpu.exp b/gdb/testsuite/gdb.btrace/cpu.exp new file mode 100644 index 0000000..bd4245c --- /dev/null +++ b/gdb/testsuite/gdb.btrace/cpu.exp @@ -0,0 +1,76 @@ +# 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 . + +gdb_start + +proc test_good { arg } { + gdb_test_no_output "set record btrace cpu $arg" "set cpu $arg" + gdb_test "show record btrace cpu" "btrace cpu is '$arg'\." \ + "show cpu $arg" +} + +proc test_bad { arg current } { + gdb_test "set record btrace cpu $arg" \ + "Bad format\. See \"help set record btrace cpu\"\." \ + "set cpu $arg" + gdb_test "show record btrace cpu" "btrace cpu is '$current'\." \ + "show cpu $arg" +} + +proc test_junk { arg junk current } { + gdb_test "set record btrace cpu $arg" \ + "Trailing junk: '$junk'\." \ + "set cpu $arg" + gdb_test "show record btrace cpu" "btrace cpu is '$current'\." \ + "show cpu $arg" +} + +gdb_test "show record btrace cpu" "btrace cpu is 'auto'\." "default cpu" + +gdb_test "set record" \ + "\"set record\" must be followed by an apporpriate subcommand.*" \ + "set record" +gdb_test "set record btrace" \ + "\"set record btrace\" must be followed by an apporpriate subcommand.*" \ + "set record btrace" +test_bad "" "auto" + +test_good "intel: 0/0" +test_good "intel: 0/0/1" + +# We omit a zero stepping in the output. +gdb_test_no_output "set record btrace cpu intel: 0/0/0" \ + "set cpu intel: 0/0/0" +gdb_test "show record btrace cpu" "btrace cpu is 'intel: 0/0'\." \ + "show cpu intel: 0/0/0" + +test_good "auto" +test_good "none" + +test_bad "intel: foo" "none" +test_bad "intel: 0" "none" +test_bad "intel: 0/" "none" +test_bad "intel: 0/foo" "none" +test_bad "intel: foo/bar" "none" +test_bad "intel: foo/0" "none" +test_bad "intel: 0x0/0" "none" + +test_junk "intel: 0/0 foo" " foo" "none" +test_junk "intel: 0/0x0" "x0" "none" +test_junk "intel: 0/0/foo" "/foo" "none" +test_junk "intel: 0/0/0 foo" " foo" "none" +test_junk "intel: 0/0/0x0" "x0" "none"