From patchwork Tue Mar 21 15:46:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Willgerodt, Felix" X-Patchwork-Id: 66698 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 54459384D156 for ; Tue, 21 Mar 2023 15:48:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 54459384D156 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1679413683; bh=GB6gW75nXyU4HCp8fREZCu3FV7Ywudc7e0zaU8yTo6A=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=g9xoO/GnYpgVtkz7xbrgo3zIsoOlTfZEuwSDlkd4l4h+ZXLScW14oHYs4q4hB0yYh Ep43KQGe7eQc4m6X7ZMa/7/9SlNNHCvk3CzysfZGg/zKNIqhTA6Xqao/25S0/9/bEC 1HN0RQ8ADNiHFKoB6X1DpwM8ih8lRsRXAvJeuzw0= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by sourceware.org (Postfix) with ESMTPS id 139933858421 for ; Tue, 21 Mar 2023 15:47:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 139933858421 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="340517727" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="340517727" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:07 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10656"; a="681530266" X-IronPort-AV: E=Sophos;i="5.98,279,1673942400"; d="scan'208";a="681530266" Received: from mulfelix.iul.intel.com (HELO localhost) ([172.28.49.163]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Mar 2023 08:47:06 -0700 To: gdb-patches@sourceware.org Cc: Felix Willgerodt Subject: [PATCH v8 05/10] python: Introduce gdb.RecordAuxiliary class. Date: Tue, 21 Mar 2023 16:46:21 +0100 Message-Id: <20230321154626.448816-6-felix.willgerodt@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230321154626.448816-1-felix.willgerodt@intel.com> References: <20230321154626.448816-1-felix.willgerodt@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Felix Willgerodt via Gdb-patches From: "Willgerodt, Felix" Reply-To: Felix Willgerodt Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Auxiliary instructions are no real instructions and get their own object class, similar to gaps. gdb.Record.instruction_history is now possibly a list of gdb.RecordInstruction, gdb.RecordGap or gdb.RecordAuxiliary objects. This patch is in preparation for the new ptwrite feature, which is based on auxiliary instructions. --- gdb/doc/python.texi | 13 +++++++ gdb/python/py-record-btrace.c | 35 +++++++++++------ gdb/python/py-record.c | 73 ++++++++++++++++++++++++++++++++++- gdb/python/py-record.h | 3 ++ 4 files changed, 111 insertions(+), 13 deletions(-) diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 54d5660543a..31243b8ec47 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -3914,6 +3914,19 @@ the current recording method. A human readable string with the reason for the gap. @end defvar +Some @value{GDBN} features write auxiliary information into the execution +history. This information is represented by a @code{gdb.RecordAuxiliary} object +in the instruction list. It has the following attributes: + +@defvar RecordAuxiliary.number +An integer identifying this auxiliary. @code{number} corresponds to the numbers +seen in @code{record instruction-history} (@pxref{Process Record and Replay}). +@end defvar + +@defvar RecordAuxiliary.data +A string representation of the auxiliary data. +@end defvar + A @code{gdb.RecordFunctionSegment} object has the following attributes: @defvar RecordFunctionSegment.number diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c index 4af86672d26..16925eadd7a 100644 --- a/gdb/python/py-record-btrace.c +++ b/gdb/python/py-record-btrace.c @@ -45,7 +45,8 @@ struct btpy_list_object { /* Stride size. */ Py_ssize_t step; - /* Either &BTPY_CALL_TYPE or &RECPY_INSN_TYPE. */ + /* Either &recpy_func_type, &recpy_insn_type, &recpy_aux_type or + &recpy_gap_type. */ PyTypeObject* element_type; }; @@ -141,10 +142,11 @@ btrace_func_from_recpy_func (const PyObject * const pyobject) } /* Looks at the recorded item with the number NUMBER and create a - gdb.RecordInstruction or gdb.RecordGap object for it accordingly. */ + gdb.RecordInstruction, gdb.RecordGap or gdb.RecordAuxiliary object + for it accordingly. */ static PyObject * -btpy_insn_or_gap_new (thread_info *tinfo, Py_ssize_t number) +btpy_item_new (thread_info *tinfo, Py_ssize_t number) { btrace_insn_iterator iter; int err_code; @@ -163,6 +165,14 @@ btpy_insn_or_gap_new (thread_info *tinfo, Py_ssize_t number) return recpy_gap_new (err_code, err_string, number); } + const struct btrace_insn *insn = btrace_insn_get (&iter); + gdb_assert (insn != nullptr); + + if (insn->iclass == BTRACE_INSN_AUX) + return recpy_aux_new + (iter.btinfo->aux_data.at (insn->aux_data_index).c_str (), number); + + return recpy_insn_new (tinfo, RECORD_METHOD_BTRACE, number); } @@ -441,8 +451,10 @@ btpy_list_length (PyObject *self) } /* Implementation of - BtraceList.__getitem__ (self, key) -> BtraceInstruction and - BtraceList.__getitem__ (self, key) -> BtraceFunctionCall. */ + BtraceList.__getitem__ (self, key) -> BtraceInstruction, + BtraceList.__getitem__ (self, key) -> BtraceFunctionCall, + BtraceList.__getitem__ (self, key) -> BtraceAuxilliary and + BtraceList.__getitem__ (self, key) -> BtraceGap. */ static PyObject * btpy_list_item (PyObject *self, Py_ssize_t index) @@ -456,10 +468,10 @@ btpy_list_item (PyObject *self, Py_ssize_t index) number = obj->first + (obj->step * index); - if (obj->element_type == &recpy_insn_type) - return recpy_insn_new (obj->thread, RECORD_METHOD_BTRACE, number); - else + if (obj->element_type == &recpy_func_type) return recpy_func_new (obj->thread, RECORD_METHOD_BTRACE, number); + else + return btpy_item_new (obj->thread, number); } /* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList. */ @@ -646,8 +658,7 @@ recpy_bt_replay_position (PyObject *self, void *closure) if (tinfo->btrace.replay == NULL) Py_RETURN_NONE; - return btpy_insn_or_gap_new (tinfo, - btrace_insn_number (tinfo->btrace.replay)); + return btpy_item_new (tinfo, btrace_insn_number (tinfo->btrace.replay)); } /* Implementation of @@ -669,7 +680,7 @@ recpy_bt_begin (PyObject *self, void *closure) Py_RETURN_NONE; btrace_insn_begin (&iterator, &tinfo->btrace); - return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator)); + return btpy_item_new (tinfo, btrace_insn_number (&iterator)); } /* Implementation of @@ -691,7 +702,7 @@ recpy_bt_end (PyObject *self, void *closure) Py_RETURN_NONE; btrace_insn_end (&iterator, &tinfo->btrace); - return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator)); + return btpy_item_new (tinfo, btrace_insn_number (&iterator)); } /* Implementation of diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c index 1e40f2cded0..1afa0f25275 100644 --- a/gdb/python/py-record.c +++ b/gdb/python/py-record.c @@ -49,6 +49,12 @@ static PyTypeObject recpy_gap_type = { PyVarObject_HEAD_INIT (NULL, 0) }; +/* Python RecordAuxiliary type. */ + +PyTypeObject recpy_aux_type = { + PyVarObject_HEAD_INIT (nullptr, 0) +}; + /* Python RecordGap object. */ struct recpy_gap_object { @@ -64,6 +70,18 @@ struct recpy_gap_object Py_ssize_t number; }; +/* Python RecordAuxiliary object. */ +typedef struct +{ + PyObject_HEAD + + /* Auxiliary data. */ + const char *data; + + /* Element number. */ + Py_ssize_t number; +} recpy_aux_object; + /* Implementation of record.method. */ static PyObject * @@ -477,6 +495,43 @@ recpy_gap_reason_string (PyObject *self, void *closure) return PyUnicode_FromString (obj->reason_string); } +/* Create a new gdb.Auxiliary object. */ + +PyObject * +recpy_aux_new (const char *data, Py_ssize_t number) +{ + recpy_aux_object * const obj = PyObject_New (recpy_aux_object, + &recpy_aux_type); + + if (obj == nullptr) + return nullptr; + + obj->data = data; + obj->number = number; + + return (PyObject *) obj; +} + +/* Implementation of Auxiliary.number [int]. */ + +static PyObject * +recpy_aux_number (PyObject *self, void *closure) +{ + const recpy_aux_object * const obj = (const recpy_aux_object *) self; + + return gdb_py_object_from_longest (obj->number).release (); +} + +/* Implementation of Auxiliary.data [str]. */ + +static PyObject * +recpy_aux_data (PyObject *self, void *closure) +{ + const recpy_aux_object * const obj = (const recpy_aux_object *) self; + + return PyUnicode_FromString (obj->data); +} + /* Record method list. */ static PyMethodDef recpy_record_methods[] = { @@ -542,6 +597,14 @@ static gdb_PyGetSetDef recpy_gap_getset[] = { { NULL } }; +/* RecordAuxiliary member list. */ + +static gdb_PyGetSetDef recpy_aux_getset[] = { + { "number", recpy_aux_number, nullptr, "element number", nullptr}, + { "data", recpy_aux_data, nullptr, "data", nullptr}, + { nullptr } +}; + /* Sets up the record API in the gdb module. */ int @@ -581,10 +644,18 @@ gdbpy_initialize_record (void) recpy_gap_type.tp_doc = "GDB recorded gap object"; recpy_gap_type.tp_getset = recpy_gap_getset; + recpy_aux_type.tp_new = PyType_GenericNew; + recpy_aux_type.tp_flags = Py_TPFLAGS_DEFAULT; + recpy_aux_type.tp_basicsize = sizeof (recpy_aux_object); + recpy_aux_type.tp_name = "gdb.RecordAuxiliary"; + recpy_aux_type.tp_doc = "GDB recorded auxiliary object"; + recpy_aux_type.tp_getset = recpy_aux_getset; + if (PyType_Ready (&recpy_record_type) < 0 || PyType_Ready (&recpy_insn_type) < 0 || PyType_Ready (&recpy_func_type) < 0 - || PyType_Ready (&recpy_gap_type) < 0) + || PyType_Ready (&recpy_gap_type) < 0 + || PyType_Ready (&recpy_aux_type) < 0) return -1; else return 0; diff --git a/gdb/python/py-record.h b/gdb/python/py-record.h index 6eec71e06e7..75bf6fae935 100644 --- a/gdb/python/py-record.h +++ b/gdb/python/py-record.h @@ -71,4 +71,7 @@ extern PyObject *recpy_func_new (thread_info *thread, enum record_method method, extern PyObject *recpy_gap_new (int reason_code, const char *reason_string, Py_ssize_t number); +/* Create a new gdb.RecordGap object. */ +extern PyObject *recpy_aux_new (const char *data, Py_ssize_t number); + #endif /* PYTHON_PY_RECORD_H */