[PATCH v2 3/3] btrace: pretend we're not replaying when generating a core file

Markus Metzger
2014-06-24T08:52:03Z

When generating a core file using the "generate-core-file" command while
replaying with the btrace record target, we won't be able to access all
registers and all memory. This leads to an assertion.

Pretend that we are not replaying while generating a core file. This will
forward fetch and store registers as well as xfer memory calls to the target
beneath.

2014-06-24 Markus Metzger <markus.t.metzger@intel.com>

* record-btrace.c (record_btrace_generating_corefile)
(record_btrace_prepare_to_generate_core)
(record_btrace_done_generating_core): New.
(record_btrace_xfer_partial, record_btrace_fetch_registers)
(record_btrace_store_registers, record_btrace_prepare_to_store):
Forward request when generating a core file.
(init_record_btrace_ops): Set to_prepare_to_generate_core and
to_done_generating_core.

testsuite/
* gdb.btrace/gcore.exp: New.
---
gdb/record-btrace.c | 28 +++++++++++++++++++++++---
gdb/testsuite/gdb.btrace/gcore.exp | 41 ++++++++++++++++++++++++++++++++++++++
2 files changed, 66 insertions(+), 3 deletions(-)
create mode 100644 gdb/testsuite/gdb.btrace/gcore.exp

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 6a9bfe1..a47aa95 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -68,6 +68,9 @@ static enum exec_direction_kind record_btrace_resume_exec_dir = EXEC_FORWARD;
/* The async event handler for reverse/replay execution. */
static struct async_event_handler *record_btrace_async_inferior_event_handler;

+/* A flag indicating that we are currently generating a core file. */
+static int record_btrace_generating_corefile;
+
/* Print a record-btrace debug message. Use do ... while (0) to avoid
ambiguities when used in if statements. */

@@ -854,6 +857,7 @@ record_btrace_xfer_partial (struct target_ops *ops, enum target_object object,

/* Filter out requests that don't make sense during replay. */
if (replay_memory_access == replay_memory_access_read_only
+ && !record_btrace_generating_corefile
&& record_btrace_is_replaying (ops))
{
switch (object)
@@ -969,7 +973,7 @@ record_btrace_fetch_registers (struct target_ops *ops,
gdb_assert (tp != NULL);

replay = tp->btrace.replay;
- if (replay != NULL)
+ if (replay != NULL && !record_btrace_generating_corefile)
{
const struct btrace_insn *insn;
struct gdbarch *gdbarch;
@@ -1010,7 +1014,7 @@ record_btrace_store_registers (struct target_ops *ops,
{
struct target_ops *t;

- if (record_btrace_is_replaying (ops))
+ if (!record_btrace_generating_corefile && record_btrace_is_replaying (ops))
error (_("This record target does not allow writing registers."));

gdb_assert (may_write_registers != 0);
@@ -1033,7 +1037,7 @@ record_btrace_prepare_to_store (struct target_ops *ops,
{
struct target_ops *t;

- if (record_btrace_is_replaying (ops))
+ if (!record_btrace_generating_corefile && record_btrace_is_replaying (ops))
return;

for (t = ops->beneath; t != NULL; t = t->beneath)
@@ -1939,6 +1943,22 @@ record_btrace_execution_direction (struct target_ops *self)
return record_btrace_resume_exec_dir;
}

+/* The to_prepare_to_generate_core target method. */
+
+static void
+record_btrace_prepare_to_generate_core (struct target_ops *self)
+{
+ record_btrace_generating_corefile = 1;
+}
+
+/* The to_done_generating_core target method. */
+
+static void
+record_btrace_done_generating_core (struct target_ops *self)
+{
+ record_btrace_generating_corefile = 0;
+}
+
/* Initialize the record-btrace target ops. */

static void
@@ -1983,6 +2003,8 @@ init_record_btrace_ops (void)
ops->to_can_execute_reverse = record_btrace_can_execute_reverse;
ops->to_decr_pc_after_break = record_btrace_decr_pc_after_break;
ops->to_execution_direction = record_btrace_execution_direction;
+ ops->to_prepare_to_generate_core = record_btrace_prepare_to_generate_core;
+ ops->to_done_generating_core = record_btrace_done_generating_core;
ops->to_stratum = record_stratum;
ops->to_magic = OPS_MAGIC;
}
diff --git a/gdb/testsuite/gdb.btrace/gcore.exp b/gdb/testsuite/gdb.btrace/gcore.exp
new file mode 100644
index 0000000..1ff4f27
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/gcore.exp
@@ -0,0 +1,41 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2014 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <markus.t.metzger@intel.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# start inferior
+standard_testfile x86-record_goto.S
+if [prepare_for_testing gcore.exp $testfile $srcfile] {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+# trace the call to the test function
+gdb_test_no_output "record btrace"
+gdb_test "next" ".*main\.3.*"
+
+# start replaying
+gdb_test "record goto begin" ".*main\.2.*"
+
+# generate a core file - this used to assert
+gdb_test "generate-core-file core" "Saved corefile core"
--
1.8.3.1