+2017-02-01 Markus Metzger <markus.t.metzger@intel.com>
+
+ * btrace.c (btrace_enable): Do not call btrace_add_pc for
+ BTRACE_FORMAT_PT or if can_access_registers_ptid returns false.
+ (btrace_fetch): Assert can_access_registers_ptid.
+ * record-btrace.c (require_btrace_thread, record_btrace_info): Call
+ validate_registers_access.
+
2017-02-01 Markus Metzger <markus.t.metzger@intel.com>
* gdbthread.h (can_access_registers_ptid): New.
tp->btrace.target = target_enable_btrace (tp->ptid, conf);
- /* Add an entry for the current PC so we start tracing from where we
- enabled it. */
- if (tp->btrace.target != NULL)
- btrace_add_pc (tp);
+ /* We're done if we failed to enable tracing. */
+ if (tp->btrace.target == NULL)
+ return;
+
+ /* We need to undo the enable in case of errors. */
+ TRY
+ {
+ /* Add an entry for the current PC so we start tracing from where we
+ enabled it.
+
+ If we can't access TP's registers, TP is most likely running. In this
+ case, we can't really say where tracing was enabled so it should be
+ safe to simply skip this step.
+
+ This is not relevant for BTRACE_FORMAT_PT since the trace will already
+ start at the PC at which tracing was enabled. */
+ if (conf->format != BTRACE_FORMAT_PT
+ && can_access_registers_ptid (tp->ptid))
+ btrace_add_pc (tp);
+ }
+ CATCH (exception, RETURN_MASK_ALL)
+ {
+ btrace_disable (tp);
+
+ throw_exception (exception);
+ }
+ END_CATCH
}
/* See btrace.h. */
if (btinfo->replay != NULL)
return;
+ /* We should not be called on running or exited threads. */
+ gdb_assert (can_access_registers_ptid (tp->ptid));
+
btrace_data_init (&btrace);
cleanup = make_cleanup_btrace_data (&btrace);
if (tp == NULL)
error (_("No thread."));
+ validate_registers_access ();
+
btrace_fetch (tp);
if (btrace_is_empty (tp))
if (tp == NULL)
error (_("No thread."));
+ validate_registers_access ();
+
btinfo = &tp->btrace;
conf = btrace_conf (btinfo);
+2017-02-01 Markus Metzger <markus.t.metzger@intel.com>
+
+ * gdb.btrace/enable-running.c: New.
+ * gdb.btrace/enable-running.exp: New.
+
2017-01-27 Walfred Tedeschi <walfred.tedeschi@intel.com>
* gdb.arch/amd64-gs_base.c: New file.
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2017 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 <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <unistd.h>
+
+#define NTHREADS 3
+
+static void *
+test (void *arg)
+{
+ /* Let's hope this is long enough for GDB to enable tracing and check that
+ everything is working as expected. */
+ sleep (10);
+
+ return arg;
+}
+
+int
+main (void)
+{
+ pthread_t th[NTHREADS];
+ int i;
+
+ for (i = 0; i < NTHREADS; ++i)
+ pthread_create (&th[i], NULL, test, NULL);
+
+ test (NULL); /* bp.1 */
+
+ for (i = 0; i < NTHREADS; ++i)
+ pthread_join (th[i], NULL);
+
+ return 0;
+}
--- /dev/null
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2017 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 <http://www.gnu.org/licenses/>.
+
+if { [skip_btrace_tests] } { return -1 }
+
+standard_testfile
+if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" "$binfile" executable {debug}] != "" } {
+ return -1
+}
+
+# We need to enable non-stop mode for the remote case.
+save_vars { GDBFLAGS } {
+ append GDBFLAGS " -ex \"set non-stop on\""
+ clean_restart $testfile
+}
+
+if ![runto_main] {
+ return -1
+}
+
+set bp_1 [gdb_get_line_number "bp.1" $srcfile]
+
+gdb_breakpoint $bp_1
+gdb_continue_to_breakpoint "cont to $bp_1" ".*$bp_1\r\n.*"
+gdb_test "cont&" "Continuing\."
+
+# All threads are running. Let's start recording.
+gdb_test_no_output "record btrace"
+
+proc check_tracing_enabled { thread } {
+ global gdb_prompt
+
+ with_test_prefix "thread $thread" {
+ gdb_test "thread $thread" "(running).*" "is running"
+
+ # We can't read the trace while the thread is running.
+ gdb_test "info record" "Selected thread is running\." \
+ "info record while running"
+
+ # Try various commands that try to read trace.
+ gdb_test "record instruction-history" "Selected thread is running\."
+ gdb_test "record function-call-history" "Selected thread is running\."
+
+ # Including reverse-stepping commands.
+ gdb_test "reverse-continue" "\[Ss\]elected thread is running\."
+ gdb_test "reverse-step" "\[Ss\]elected thread is running\."
+ gdb_test "reverse-next" "\[Ss\]elected thread is running\."
+ gdb_test "reverse-finish" "\[Ss\]elected thread is running\."
+
+ # Stop the thread before reading the trace.
+ gdb_test_multiple "interrupt" "interrupt" {
+ -re "interrupt\r\n$gdb_prompt " {
+ pass "interrupt"
+ }
+ }
+ # Wait until the thread actually stopped.
+ gdb_test_multiple "" "stopped" {
+ -re "Thread $thread.*stopped\." {
+ pass "stopped"
+ }
+ }
+ # We will consume the thread's current location as part of the
+ # "info record" output.
+ gdb_test "info record" [multi_line \
+ "Active record target: record-btrace" \
+ "Recording format: .*" \
+ "Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*" \
+ ]
+
+ # Continue the thread again.
+ gdb_test "cont&" "Continuing\."
+ }
+}
+
+# Check that recording was started on each thread.
+foreach thread {1 2 3 4} {
+ check_tracing_enabled $thread
+}
+
+# Stop recording while all threads are running.
+gdb_test "record stop" "Process record is stopped \[^\\\r\\\n\]*"