From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9418 invoked by alias); 27 Jan 2017 14:40:43 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 9149 invoked by uid 89); 27 Jan 2017 14:40:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.0 required=5.0 tests=AWL,BAYES_00,KAM_LAZY_DOMAIN_SECURITY,RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=3696, 3699 X-HELO: mga11.intel.com Received: from mga11.intel.com (HELO mga11.intel.com) (192.55.52.93) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 27 Jan 2017 14:40:20 +0000 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga102.fm.intel.com with ESMTP; 27 Jan 2017 06:40:19 -0800 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by FMSMGA003.fm.intel.com with ESMTP; 27 Jan 2017 06:40:17 -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 v0REeHhB030614; Fri, 27 Jan 2017 14:40:17 GMT Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id v0REeGe5000341; Fri, 27 Jan 2017 15:40:16 +0100 Received: (from twiederh@localhost) by ulvlx001.iul.intel.com with œ id v0REeGM1000337; Fri, 27 Jan 2017 15:40:16 +0100 From: Tim Wiederhake To: gdb-patches@sourceware.org Cc: markus.t.metzger@intel.com, palves@redhat.com, xdje42@gmail.com Subject: [PATCH v5 6/9] python: Create Python bindings for record history. Date: Fri, 27 Jan 2017 14:40:00 -0000 Message-Id: <1485527996-32506-7-git-send-email-tim.wiederhake@intel.com> In-Reply-To: <1485527996-32506-1-git-send-email-tim.wiederhake@intel.com> References: <1485527996-32506-1-git-send-email-tim.wiederhake@intel.com> X-IsSubscribed: yes X-SW-Source: 2017-01/txt/msg00622.txt.bz2 This patch adds three new functions to the gdb module in Python: - start_recording - stop_recording - current_recording start_recording and current_recording return an object of the new type gdb.Record, which can be used to access the recorded data. 2017-01-27 Tim Wiederhake gdb/ChangeLog * Makefile.in (SUBDIR_PYTHON_OBS): Add python/py-record.o. (SUBDIR_PYTHON_SRCS): Add python/py-record.c. * python/py-record.c: New file. * python/python-internal.h (gdbpy_start_recording, gdbpy_current_recording, gdpy_stop_recording, gdbpy_initialize_record): New export. * python/python.c (_initialize_python): Add gdbpy_initialize_record. (python_GdbMethods): Add gdbpy_start_recording, gdbpy_current_recording and gdbpy_stop_recording. --- gdb/Makefile.in | 2 + gdb/python/py-record.c | 227 +++++++++++++++++++++++++++++++++++++++++++ gdb/python/python-internal.h | 5 + gdb/python/python.c | 13 +++ 4 files changed, 247 insertions(+) create mode 100644 gdb/python/py-record.c diff --git a/gdb/Makefile.in b/gdb/Makefile.in index e0fe442..b4419f0 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -460,6 +460,7 @@ SUBDIR_PYTHON_OBS = \ py-param.o \ py-prettyprint.o \ py-progspace.o \ + py-record.o \ py-signalevent.o \ py-stopevent.o \ py-symbol.o \ @@ -500,6 +501,7 @@ SUBDIR_PYTHON_SRCS = \ python/py-param.c \ python/py-prettyprint.c \ python/py-progspace.c \ + python/py-record.c \ python/py-signalevent.c \ python/py-stopevent.c \ python/py-symbol.c \ diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c new file mode 100644 index 0000000..27ecbb6 --- /dev/null +++ b/gdb/python/py-record.c @@ -0,0 +1,227 @@ +/* Python interface to record targets. + + Copyright 2016-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 . */ + +#include "defs.h" +#include "inferior.h" +#include "record.h" +#include "python-internal.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 = { + PyVarObject_HEAD_INIT (NULL, 0) +}; + +/* Implementation of record.ptid. */ + +static PyObject * +recpy_ptid (PyObject *self, void* closure) +{ + const recpy_record_object * const obj = (recpy_record_object *) self; + + return gdbpy_create_ptid_object (obj->ptid); +} + +/* Implementation of record.method. */ + +static PyObject * +recpy_method (PyObject *self, void* closure) +{ + return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); +} + +/* Implementation of record.format. */ + +static PyObject * +recpy_format (PyObject *self, void* closure) +{ + return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); +} + +/* Implementation of record.goto (instruction) -> None. */ + +static PyObject * +recpy_goto (PyObject *self, PyObject *value) +{ + return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); +} + +/* Implementation of record.replay_position [instruction] */ + +static PyObject * +recpy_replay_position (PyObject *self, void *closure) +{ + return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); +} + +/* Implementation of record.instruction_history [list]. */ + +static PyObject * +recpy_instruction_history (PyObject *self, void* closure) +{ + return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); +} + +/* Implementation of record.function_call_history [list]. */ + +static PyObject * +recpy_function_call_history (PyObject *self, void* closure) +{ + return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); +} + +/* Implementation of record.begin [instruction]. */ + +static PyObject * +recpy_begin (PyObject *self, void* closure) +{ + return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); +} + +/* Implementation of record.end [instruction]. */ + +static PyObject * +recpy_end (PyObject *self, void* closure) +{ + return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); +} + +/* Record method list. */ + +static PyMethodDef recpy_record_methods[] = { + { "goto", recpy_goto, METH_VARARGS, + "goto (instruction|function_call) -> None.\n\ +Rewind to given location."}, + { NULL } +}; + +/* Record member list. */ + +static PyGetSetDef recpy_record_getset[] = { + { "ptid", recpy_ptid, NULL, "Current thread.", NULL }, + { "method", recpy_method, NULL, "Current recording method.", NULL }, + { "format", recpy_format, NULL, "Current recording format.", NULL }, + { "replay_position", recpy_replay_position, NULL, "Current replay position.", + NULL }, + { "instruction_history", recpy_instruction_history, NULL, + "List of instructions in current recording.", NULL }, + { "function_call_history", recpy_function_call_history, NULL, + "List of function calls in current recording.", NULL }, + { "begin", recpy_begin, NULL, + "First instruction in current recording.", NULL }, + { "end", recpy_end, NULL, + "One past the last instruction in current recording. This is typically \ +the current instruction and is used for e.g. record.goto (record.end).", NULL }, + { NULL } +}; + +/* Sets up the record API in the gdb module. */ + +int +gdbpy_initialize_record (void) +{ + recpy_record_type.tp_new = PyType_GenericNew; + recpy_record_type.tp_flags = Py_TPFLAGS_DEFAULT; + recpy_record_type.tp_basicsize = sizeof (recpy_record_object); + recpy_record_type.tp_name = "gdb.Record"; + recpy_record_type.tp_doc = "GDB record object"; + recpy_record_type.tp_methods = recpy_record_methods; + recpy_record_type.tp_getset = recpy_record_getset; + + return PyType_Ready (&recpy_record_type); +} + +/* Implementation of gdb.start_recording (method) -> gdb.Record. */ + +PyObject * +gdbpy_start_recording (PyObject *self, PyObject *args) +{ + const char *method = NULL; + const char *format = NULL; + PyObject *ret = NULL; + + if (!PyArg_ParseTuple (args, "|ss", &method, &format)) + return NULL; + + TRY + { + record_start (method, format, 0); + ret = gdbpy_current_recording (self, args); + } + CATCH (except, RETURN_MASK_ALL) + { + gdbpy_convert_exception (except); + } + END_CATCH + + return ret; +} + +/* Implementation of gdb.current_recording (self) -> gdb.Record. */ + +PyObject * +gdbpy_current_recording (PyObject *self, PyObject *args) +{ + recpy_record_object *ret = NULL; + + if (find_record_target () == NULL) + Py_RETURN_NONE; + + ret = PyObject_New (recpy_record_object, &recpy_record_type); + ret->ptid = inferior_ptid; + ret->method = target_record_method (inferior_ptid); + + return (PyObject *) ret; +} + +/* Implementation of gdb.stop_recording (self) -> None. */ + +PyObject * +gdbpy_stop_recording (PyObject *self, PyObject *args) +{ + PyObject *ret = NULL; + + TRY + { + record_stop (0); + ret = Py_None; + Py_INCREF (Py_None); + } + CATCH (except, RETURN_MASK_ALL) + { + gdbpy_convert_exception (except); + } + END_CATCH + + return ret; +} diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index e2ebc1b..c6af9f7 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -369,6 +369,9 @@ PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *); PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw); PyObject *gdbpy_lookup_global_symbol (PyObject *self, PyObject *args, PyObject *kw); +PyObject *gdbpy_start_recording (PyObject *self, PyObject *args); +PyObject *gdbpy_current_recording (PyObject *self, PyObject *args); +PyObject *gdbpy_stop_recording (PyObject *self, PyObject *args); PyObject *gdbpy_newest_frame (PyObject *self, PyObject *args); PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args); PyObject *gdbpy_block_for_pc (PyObject *self, PyObject *args); @@ -436,6 +439,8 @@ int gdbpy_initialize_values (void) CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; int gdbpy_initialize_frames (void) CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; +int gdbpy_initialize_record (void) + CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; int gdbpy_initialize_symtabs (void) CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; int gdbpy_initialize_commands (void) diff --git a/gdb/python/python.c b/gdb/python/python.c index ab5a6a4..ea98b64 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -1696,6 +1696,7 @@ message == an error message without a stack will be printed."), || gdbpy_initialize_values () < 0 || gdbpy_initialize_frames () < 0 || gdbpy_initialize_commands () < 0 + || gdbpy_initialize_record () < 0 || gdbpy_initialize_symbols () < 0 || gdbpy_initialize_symtabs () < 0 || gdbpy_initialize_blocks () < 0 @@ -1903,6 +1904,18 @@ Return the selected frame object." }, "stop_reason_string (Integer) -> String.\n\ Return a string explaining unwind stop reason." }, + { "start_recording", gdbpy_start_recording, METH_VARARGS, + "start_recording ([method] [, format]) -> gdb.Record.\n\ +Start recording with the given method. If no method is given, will fall back\n\ +to the system default method. If no format is given, will fall back to the\n\ +default format for the given method."}, + { "current_recording", gdbpy_current_recording, METH_NOARGS, + "current_recording () -> gdb.Record.\n\ +Return current recording object." }, + { "stop_recording", gdbpy_stop_recording, METH_NOARGS, + "stop_recording () -> None.\n\ +Stop current recording." }, + { "lookup_type", (PyCFunction) gdbpy_lookup_type, METH_VARARGS | METH_KEYWORDS, "lookup_type (name [, block]) -> type\n\ -- 2.7.4