aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Wiederhake <tim.wiederhake@intel.com>2017-05-02 11:35:54 +0200
committerTim Wiederhake <tim.wiederhake@intel.com>2017-05-02 11:35:54 +0200
commitae20e79ae852fee8f7d42701a54a95de3b79ecea (patch)
tree616d593dcb7ef8249449028538998a7ff6a180e4
parent8d0050ea192c41349c1f2b000866c1bdb761abeb (diff)
downloadfsf-binutils-gdb-ae20e79ae852fee8f7d42701a54a95de3b79ecea.zip
fsf-binutils-gdb-ae20e79ae852fee8f7d42701a54a95de3b79ecea.tar.gz
fsf-binutils-gdb-ae20e79ae852fee8f7d42701a54a95de3b79ecea.tar.bz2
Python: Use correct ptid in btrace recording
The user would always get the instruction_history and function_call_history objects of the current thread, not the thread for which the gdb.Record object was created. The attached testcase fails without this patch and passes with the patch.
-rw-r--r--gdb/ChangeLog12
-rw-r--r--gdb/btrace.c8
-rw-r--r--gdb/python/py-record-btrace.c32
-rw-r--r--gdb/python/py-record.c17
-rw-r--r--gdb/python/py-record.h40
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.python/py-record-btrace-threads.c58
-rw-r--r--gdb/testsuite/gdb.python/py-record-btrace-threads.exp81
8 files changed, 224 insertions, 29 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 78e4469..d4741b0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
+ * btrace.c (btrace_fetch): Set inferior_ptid.
+ * python/py-record-btrace.c: Add "py-record.h" include.
+ (recpy_bt_format, recpy_bt_replay_position, recpy_bt_begin,
+ recpy_bt_end, recpy_bt_instruction_history,
+ recpy_bt_function_call_history, recpy_bt_goto): Use ptid stored
+ in gdb.Record object instead of current ptid.
+ * python/py-record.c: Include new "py-record.h" file.
+ (recpy_record_object): Moved to py-record.h.
+ * python/py-record.h: New file.
+
+2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
+
* python/py-record-btrace.c (BTPY_REQUIRE_VALID_INSN,
BTPY_REQUIRE_VALID_CALL, recpy_bt_function_call_history): Fix
indentation.
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 238df0a..3801086 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -1802,11 +1802,17 @@ btrace_fetch (struct thread_info *tp)
if (btinfo->replay != NULL)
return;
+ /* With CLI usage, TP->PTID always equals INFERIOR_PTID here. Now that we
+ can store a gdb.Record object in Python referring to a different thread
+ than the current one, temporarily set INFERIOR_PTID. */
+ cleanup = save_inferior_ptid ();
+ inferior_ptid = tp->ptid;
+
/* 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);
+ make_cleanup_btrace_data (&btrace);
/* Let's first try to extend the trace we already have. */
if (btinfo->end != NULL)
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 6ba9d7e..5f9264d 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -22,6 +22,7 @@
#include "gdbcmd.h"
#include "gdbthread.h"
#include "btrace.h"
+#include "py-record.h"
#include "py-record-btrace.h"
#include "disasm.h"
@@ -734,7 +735,8 @@ recpy_bt_method (PyObject *self, void *closure)
PyObject *
recpy_bt_format (PyObject *self, void *closure)
{
- const struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
+ const recpy_record_object * const record = (recpy_record_object *) self;
+ const struct thread_info * const tinfo = find_thread_ptid (record->ptid);
const struct btrace_config * config;
if (tinfo == NULL)
@@ -754,7 +756,8 @@ recpy_bt_format (PyObject *self, void *closure)
PyObject *
recpy_bt_replay_position (PyObject *self, void *closure)
{
- const struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
+ const recpy_record_object * const record = (recpy_record_object *) self;
+ const struct thread_info * const tinfo = find_thread_ptid (record->ptid);
if (tinfo == NULL)
Py_RETURN_NONE;
@@ -762,7 +765,7 @@ recpy_bt_replay_position (PyObject *self, void *closure)
if (tinfo->btrace.replay == NULL)
Py_RETURN_NONE;
- return btpy_insn_new (inferior_ptid,
+ return btpy_insn_new (record->ptid,
btrace_insn_number (tinfo->btrace.replay));
}
@@ -772,7 +775,8 @@ recpy_bt_replay_position (PyObject *self, void *closure)
PyObject *
recpy_bt_begin (PyObject *self, void *closure)
{
- struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
+ const recpy_record_object * const record = (recpy_record_object *) self;
+ struct thread_info * const tinfo = find_thread_ptid (record->ptid);
struct btrace_insn_iterator iterator;
if (tinfo == NULL)
@@ -784,7 +788,7 @@ recpy_bt_begin (PyObject *self, void *closure)
Py_RETURN_NONE;
btrace_insn_begin (&iterator, &tinfo->btrace);
- return btpy_insn_new (inferior_ptid, btrace_insn_number (&iterator));
+ return btpy_insn_new (record->ptid, btrace_insn_number (&iterator));
}
/* Implementation of
@@ -793,7 +797,8 @@ recpy_bt_begin (PyObject *self, void *closure)
PyObject *
recpy_bt_end (PyObject *self, void *closure)
{
- struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
+ const recpy_record_object * const record = (recpy_record_object *) self;
+ struct thread_info * const tinfo = find_thread_ptid (record->ptid);
struct btrace_insn_iterator iterator;
if (tinfo == NULL)
@@ -805,7 +810,7 @@ recpy_bt_end (PyObject *self, void *closure)
Py_RETURN_NONE;
btrace_insn_end (&iterator, &tinfo->btrace);
- return btpy_insn_new (inferior_ptid, btrace_insn_number (&iterator));
+ return btpy_insn_new (record->ptid, btrace_insn_number (&iterator));
}
/* Implementation of
@@ -814,7 +819,8 @@ recpy_bt_end (PyObject *self, void *closure)
PyObject *
recpy_bt_instruction_history (PyObject *self, void *closure)
{
- struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
+ const recpy_record_object * const record = (recpy_record_object *) self;
+ struct thread_info * const tinfo = find_thread_ptid (record->ptid);
struct btrace_insn_iterator iterator;
unsigned long first = 0;
unsigned long last = 0;
@@ -833,7 +839,7 @@ recpy_bt_instruction_history (PyObject *self, void *closure)
btrace_insn_end (&iterator, &tinfo->btrace);
last = btrace_insn_number (&iterator);
- return btpy_list_new (inferior_ptid, first, last, 1, &btpy_insn_type);
+ return btpy_list_new (record->ptid, first, last, 1, &btpy_insn_type);
}
/* Implementation of
@@ -842,7 +848,8 @@ recpy_bt_instruction_history (PyObject *self, void *closure)
PyObject *
recpy_bt_function_call_history (PyObject *self, void *closure)
{
- struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
+ const recpy_record_object * const record = (recpy_record_object *) self;
+ struct thread_info * const tinfo = find_thread_ptid (record->ptid);
struct btrace_call_iterator iterator;
unsigned long first = 0;
unsigned long last = 0;
@@ -861,7 +868,7 @@ recpy_bt_function_call_history (PyObject *self, void *closure)
btrace_call_end (&iterator, &tinfo->btrace);
last = btrace_call_number (&iterator);
- return btpy_list_new (inferior_ptid, first, last, 1, &btpy_call_type);
+ return btpy_list_new (record->ptid, first, last, 1, &btpy_call_type);
}
/* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None. */
@@ -869,7 +876,8 @@ recpy_bt_function_call_history (PyObject *self, void *closure)
PyObject *
recpy_bt_goto (PyObject *self, PyObject *args)
{
- struct thread_info * const tinfo = find_thread_ptid (inferior_ptid);
+ const recpy_record_object * const record = (recpy_record_object *) self;
+ struct thread_info * const tinfo = find_thread_ptid (record->ptid);
const btpy_object *obj;
if (tinfo == NULL || btrace_is_empty (tinfo))
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index 60c0a7c..63cd293 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -18,26 +18,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
-#include "inferior.h"
-#include "record.h"
-#include "python-internal.h"
+#include "py-record.h"
#include "py-record-btrace.h"
#include "py-record-full.h"
#include "target.h"
-/* Python Record object. */
-
-typedef struct
-{
- PyObject_HEAD
-
- /* The ptid this object refers to. */
- ptid_t ptid;
-
- /* The current recording method. */
- enum record_method method;
-} recpy_record_object;
-
/* Python Record type. */
static PyTypeObject recpy_record_type = {
diff --git a/gdb/python/py-record.h b/gdb/python/py-record.h
new file mode 100644
index 0000000..c386ba2
--- /dev/null
+++ b/gdb/python/py-record.h
@@ -0,0 +1,40 @@
+/* Python interface to record targets.
+
+ Copyright 2017 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#ifndef GDB_PY_RECORD_H
+#define GDB_PY_RECORD_H
+
+#include "inferior.h"
+#include "python-internal.h"
+#include "record.h"
+
+/* Python Record object. */
+
+typedef struct
+{
+ PyObject_HEAD
+
+ /* The ptid this object refers to. */
+ ptid_t ptid;
+
+ /* The current recording method. */
+ enum record_method method;
+} recpy_record_object;
+
+#endif /* GDB_PY_RECORD_H */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 2f24d47..dac5b2e 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
+
+ * gdb.python/py-record-btrace-threads.c: New file.
+ * gdb.python/py-record-btrace-threads.exp: New file.
+
2017-04-28 Sergio Durigan Junior <sergiodj@redhat.com>
PR testsuite/8595
diff --git a/gdb/testsuite/gdb.python/py-record-btrace-threads.c b/gdb/testsuite/gdb.python/py-record-btrace-threads.c
new file mode 100644
index 0000000..3dc58ca
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-record-btrace-threads.c
@@ -0,0 +1,58 @@
+/* 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>
+
+static pthread_barrier_t barrier;
+static int dummy;
+
+static void *
+func1 (void *arg)
+{
+ pthread_barrier_wait (&barrier);
+ dummy = 1; /* bp1 */
+ pthread_barrier_wait (&barrier);
+ dummy = 1;
+ pthread_barrier_wait (&barrier);
+ return arg;
+}
+
+static void *
+func2 (void *arg)
+{
+ pthread_barrier_wait (&barrier);
+ dummy = 2;
+ pthread_barrier_wait (&barrier);
+ dummy = 2;
+ pthread_barrier_wait (&barrier); /* bp2 */
+ return arg;
+}
+
+int
+main (void)
+{
+ pthread_t thread;
+
+ pthread_barrier_init (&barrier, NULL, 2);
+
+ pthread_create (&thread, NULL, func2, NULL);
+ func1 (NULL);
+
+ pthread_join (thread, NULL);
+ pthread_barrier_destroy (&barrier);
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.python/py-record-btrace-threads.exp b/gdb/testsuite/gdb.python/py-record-btrace-threads.exp
new file mode 100644
index 0000000..17fb5d0
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-record-btrace-threads.exp
@@ -0,0 +1,81 @@
+# 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/>.
+
+# Skip this test if btrace is disabled.
+
+if { [skip_btrace_tests] } {
+ untested "skipping btrace tests"
+ return -1
+}
+
+standard_testfile
+
+if { [gdb_compile_pthreads "$srcdir/$subdir/$srcfile" "$binfile" executable {debug} ] != "" } {
+ untested "failed to prepare"
+ return -1
+}
+clean_restart $testfile
+
+# Skip this test if python is disabled.
+
+load_lib gdb-python.exp
+if { [skip_python_tests] } {
+ untested "skipping python tests"
+ return -1
+}
+
+if { ![runto_main] } {
+ untested "failed to run to main"
+ return -1
+}
+
+# set up breakpoints
+gdb_breakpoint $srcfile:[gdb_get_line_number "bp1" $srcfile]
+gdb_breakpoint $srcfile:[gdb_get_line_number "bp2" $srcfile]
+
+# record data
+gdb_continue_to_breakpoint "cont to bp.1" ".*bp1.*"
+gdb_test_no_output "record btrace"
+gdb_continue_to_breakpoint "cont to bp.2" ".*bp2.*"
+
+# acquire the record objects for thread 1 and thread 2
+gdb_test "thread 1" ".*"
+gdb_test "record function-call-history" ".*" "fch thread 1"
+gdb_test_no_output "python rec1 = gdb.current_recording()"
+gdb_test "thread 2" ".*"
+gdb_test "record function-call-history" ".*" "fch thread 2"
+gdb_test_no_output "python rec2 = gdb.current_recording()"
+
+# Thread 1 is supposed to call func1 (), thread 2 is supposed to call func2 ().
+# Check that the function call history for the current thread contains a call
+# to the right function and does not contain a call to the wrong function.
+proc check_insn_for_thread { self other } {
+ with_test_prefix "checking thread $self" {
+ gdb_test_no_output "python fch = rec$self.function_call_history"
+ gdb_test_no_output "python f1calls = \{x for x in fch if x.symbol and x.symbol.name == \"func1\"\}"
+ gdb_test_no_output "python f2calls = \{x for x in fch if x.symbol and x.symbol.name == \"func2\"\}"
+
+ gdb_test "python print not f${self}calls" "False"
+ gdb_test "python print not f${other}calls" "True"
+ }
+}
+
+foreach_with_prefix thread { 1 2 } {
+ gdb_test "thread $thread"
+ check_insn_for_thread 1 2
+ check_insn_for_thread 2 1
+}