This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 3/8] Python: Use correct ptid in btrace recording
- From: Tim Wiederhake <tim dot wiederhake at intel dot com>
- To: gdb-patches at sourceware dot org
- Cc: markus dot t dot metzger at intel dot com, brobecker at adacore dot com, qiyaoltc at gmail dot com
- Date: Thu, 13 Apr 2017 16:58:31 +0200
- Subject: [PATCH 3/8] Python: Use correct ptid in btrace recording
- Authentication-results: sourceware.org; auth=none
- References: <1492095516-8650-1-git-send-email-tim.wiederhake@intel.com>
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.
2017-04-13 Tim Wiederhake <tim.wiederhake@intel.com>
gdb/ChangeLog:
* 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.
gdb/testsuite/ChangeLog:
* gdb.python/py-record-btrace-threads.c: New file.
* gdb.python/py-record-btrace-threads.exp: New file.
---
gdb/btrace.c | 8 ++-
gdb/python/py-record-btrace.c | 32 +++++----
gdb/python/py-record.c | 17 +----
gdb/python/py-record.h | 40 +++++++++++
.../gdb.python/py-record-btrace-threads.c | 58 ++++++++++++++++
.../gdb.python/py-record-btrace-threads.exp | 81 ++++++++++++++++++++++
6 files changed, 207 insertions(+), 29 deletions(-)
create mode 100644 gdb/python/py-record.h
create mode 100644 gdb/testsuite/gdb.python/py-record-btrace-threads.c
create mode 100644 gdb/testsuite/gdb.python/py-record-btrace-threads.exp
diff --git a/gdb/btrace.c b/gdb/btrace.c
index 95dc7ab..3f819e6 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -1797,11 +1797,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 9d79e2b..018b3d8 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"
@@ -740,7 +741,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)
@@ -760,7 +762,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;
@@ -768,7 +771,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));
}
@@ -778,7 +781,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)
@@ -790,7 +794,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
@@ -799,7 +803,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)
@@ -811,7 +816,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
@@ -820,7 +825,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;
@@ -839,7 +845,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
@@ -848,7 +854,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;
@@ -867,7 +874,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. */
@@ -875,7 +882,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;
PyObject *ret = NULL;
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index 72922a4..586687a 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/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..1b36f24
--- /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 } {
+ 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"
+}
+
+with_test_prefix "thread 1" {
+ check_insn_for_thread 1 2
+}
+
+with_test_prefix "thread 2" {
+ check_insn_for_thread 2 1
+}
--
2.7.4