diff options
author | Felix Willgerodt <felix.willgerodt@intel.com> | 2019-02-21 10:48:35 +0100 |
---|---|---|
committer | Felix Willgerodt <felix.willgerodt@intel.com> | 2024-08-14 11:20:56 +0200 |
commit | bea4f6fac4e0b1700188fad19499c62c46f8e70d (patch) | |
tree | d9d3efc032df5a97f253a863f2a5c602122493ec /gdb | |
parent | d5e1495d99e2a0962b69d673a8a336501a6ec5fa (diff) | |
download | binutils-bea4f6fac4e0b1700188fad19499c62c46f8e70d.zip binutils-bea4f6fac4e0b1700188fad19499c62c46f8e70d.tar.gz binutils-bea4f6fac4e0b1700188fad19499c62c46f8e70d.tar.bz2 |
python: Introduce gdb.RecordAuxiliary class.
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.
Approved-By: Markus Metzger <markus.t.metzger@intel.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/doc/python.texi | 13 | ||||
-rw-r--r-- | gdb/python/py-record-btrace.c | 84 | ||||
-rw-r--r-- | gdb/python/py-record-btrace.h | 3 | ||||
-rw-r--r-- | gdb/python/py-record.c | 62 | ||||
-rw-r--r-- | gdb/python/py-record.h | 7 |
5 files changed, 153 insertions, 16 deletions
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 86ccc14..05e5059 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -4369,6 +4369,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.@var{number} +An integer identifying this auxiliary. @var{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 36454fc..0ff2708 100644 --- a/gdb/python/py-record-btrace.c +++ b/gdb/python/py-record-btrace.c @@ -44,7 +44,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; }; @@ -140,15 +141,21 @@ 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; - btrace_find_insn_by_number (&iter, &tinfo->btrace, number); + if (btrace_find_insn_by_number (&iter, &tinfo->btrace, number) == 0) + { + PyErr_Format (gdbpy_gdb_error, _("No such instruction.")); + return nullptr; + } + err_code = btrace_insn_get_error (&iter); if (err_code != 0) @@ -162,6 +169,12 @@ 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 (tinfo, RECORD_METHOD_BTRACE, number); + return recpy_insn_new (tinfo, RECORD_METHOD_BTRACE, number); } @@ -423,6 +436,48 @@ recpy_bt_func_next (PyObject *self, void *closure) RECORD_METHOD_BTRACE, func->next); } +/* Implementation of Auxiliary.data [str] for btrace. */ + +PyObject * +recpy_bt_aux_data (PyObject *self, void *closure) +{ + const btrace_insn *insn; + const recpy_element_object *obj; + thread_info *tinfo; + btrace_insn_iterator iter; + + if (Py_TYPE (self) != &recpy_aux_type) + { + PyErr_Format (gdbpy_gdb_error, _("Must be a gdb.Auxiliary.")); + return nullptr; + } + + obj = (const recpy_element_object *) self; + tinfo = obj->thread; + + if (tinfo == nullptr || btrace_is_empty (tinfo)) + { + PyErr_Format (gdbpy_gdb_error, _("No such auxiliary object.")); + return nullptr; + } + + if (btrace_find_insn_by_number (&iter, &tinfo->btrace, obj->number) == 0) + { + PyErr_Format (gdbpy_gdb_error, _("No such auxiliary object.")); + return nullptr; + } + + insn = btrace_insn_get (&iter); + if (insn == nullptr || insn->iclass != BTRACE_INSN_AUX) + { + PyErr_Format (gdbpy_gdb_error, _("Not a valid auxiliary object.")); + return nullptr; + } + + return PyUnicode_FromString + (iter.btinfo->aux_data.at (insn->aux_data_index).c_str ()); +} + /* Implementation of BtraceList.__len__ (self) -> int. */ static Py_ssize_t @@ -439,8 +494,9 @@ 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) -> BtraceAuxiliary. */ static PyObject * btpy_list_item (PyObject *self, Py_ssize_t index) @@ -454,10 +510,13 @@ 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 if (obj->element_type == &recpy_insn_type + || obj->element_type == &recpy_aux_type) + return btpy_item_new (obj->thread, number); + else + return PyErr_Format (gdbpy_gdb_error, _("Not a valid BtraceList object.")); } /* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList. */ @@ -644,8 +703,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 @@ -667,7 +725,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 @@ -689,7 +747,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-btrace.h b/gdb/python/py-record-btrace.h index 8678e77..5010cb3 100644 --- a/gdb/python/py-record-btrace.h +++ b/gdb/python/py-record-btrace.h @@ -88,4 +88,7 @@ extern PyObject *recpy_bt_func_prev (PyObject *self, void *closure); /* Implementation of RecordFunctionSegment.next [RecordFunctionSegment]. */ extern PyObject *recpy_bt_func_next (PyObject *self, void *closure); +/* Implementation of RecordAuxiliary.decoded [str]. */ +extern PyObject *recpy_bt_aux_data (PyObject *self, void *closure); + #endif /* PYTHON_PY_RECORD_BTRACE_H */ diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c index d489126..0efd631 100644 --- a/gdb/python/py-record.c +++ b/gdb/python/py-record.c @@ -48,6 +48,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 { @@ -389,8 +395,8 @@ recpy_element_hash (PyObject *self) return obj->number; } -/* Implementation of operator == and != of RecordInstruction and - RecordFunctionSegment. */ +/* Implementation of operator == and != of RecordInstruction, + RecordFunctionSegment and RecordAuxiliary. */ static PyObject * recpy_element_richcompare (PyObject *self, PyObject *other, int op) @@ -478,6 +484,38 @@ recpy_gap_reason_string (PyObject *self, void *closure) return PyUnicode_FromString (obj->reason_string); } +/* Create a new gdb.Auxiliary object. */ + +PyObject * +recpy_aux_new (thread_info *thread, enum record_method method, + Py_ssize_t number) +{ + recpy_element_object * const obj = PyObject_New (recpy_element_object, + &recpy_aux_type); + + if (obj == NULL) + return NULL; + + obj->thread = thread; + obj->method = method; + obj->number = number; + + return (PyObject *) obj; +} + +/* Implementation of Auxiliary.data [buffer]. */ + +static PyObject * +recpy_aux_data (PyObject *self, void *closure) +{ + const recpy_element_object * const obj = (recpy_element_object *) self; + + if (obj->method == RECORD_METHOD_BTRACE) + return recpy_bt_aux_data (self, closure); + + return PyErr_Format (PyExc_NotImplementedError, _("Not implemented.")); +} + /* Record method list. */ static PyMethodDef recpy_record_methods[] = { @@ -543,6 +581,14 @@ static gdb_PyGetSetDef recpy_gap_getset[] = { { NULL } }; +/* RecordAuxiliary member list. */ + +static gdb_PyGetSetDef recpy_aux_getset[] = { + { "number", recpy_element_number, nullptr, "element number", nullptr}, + { "data", recpy_aux_data, nullptr, "data", nullptr}, + { nullptr } +}; + /* Sets up the record API in the gdb module. */ static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION @@ -582,10 +628,20 @@ 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_element_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; + recpy_aux_type.tp_richcompare = recpy_element_richcompare; + recpy_aux_type.tp_hash = recpy_element_hash; + 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 7e11610..0988584 100644 --- a/gdb/python/py-record.h +++ b/gdb/python/py-record.h @@ -59,6 +59,9 @@ extern PyTypeObject recpy_insn_type; /* Python RecordFunctionSegment type. */ extern PyTypeObject recpy_func_type; +/* Python RecordAuxiliary type. */ +extern PyTypeObject recpy_aux_type; + /* Create a new gdb.RecordInstruction object. */ extern PyObject *recpy_insn_new (thread_info *thread, enum record_method method, Py_ssize_t number); @@ -71,4 +74,8 @@ 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 (thread_info *thread, enum record_method method, + Py_ssize_t number); + #endif /* PYTHON_PY_RECORD_H */ |