[05/10] python: Introduce gdb.RecordAuxiliary class.
Commit Message
From: Felix Willgerodt <felix.willgerodt@intel.com>
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.
2019-05-29 Felix Willgerodt <felix.willgerodt@intel.com>
gdb/ChangeLog:
* py-record-btrace.c (btpy_insn_or_gap_new): Removed.
(btpy_item_new): New function.
(btpy_list_item): Call btpy_item_new instead of recpy_insn_new.
(recpy_bt_replay_position): Call btpy_item_new instead of
btpy_insn_or_gap_new.
(recpy_bt_begin): Call btpy_item_new instead of btpy_insn_or_gap_new.
(recpy_bt_end): Call btpy_item_new instead of btpy_insn_or_gap_new.
* py-record.c (recpy_aux_type): New static object.
(recpy_aux_object): New typedef.
(recpy_aux_new, recpy_aux_number, recpy_aux_data): New function.
(recpy_aux_getset): New static object.
(gdbpy_initialize_record): Initialize gdb.RecordAuxiliary type.
gdb/doc/ChangeLog:
* python.texi (gdb.RecordAuxiliary): New documentation.
---
gdb/doc/python.texi | 13 +++++++
gdb/python/py-record-btrace.c | 22 +++++++----
gdb/python/py-record.c | 73 ++++++++++++++++++++++++++++++++++-
gdb/python/py-record.h | 3 ++
4 files changed, 103 insertions(+), 8 deletions(-)
Comments
> From: felix.willgerodt@intel.com
> Cc: markus.t.metzger@intel.com, Felix Willgerodt <felix.willgerodt@intel.com>
> Date: Wed, 29 May 2019 10:47:48 +0200
>
> gdb/doc/ChangeLog:
> * python.texi (gdb.RecordAuxiliary): New documentation.
OK for this part, thanks.
Hello Felix,
> 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.
>
> 2019-05-29 Felix Willgerodt <felix.willgerodt@intel.com>
>
> gdb/ChangeLog:
> * py-record-btrace.c (btpy_insn_or_gap_new): Removed.
> (btpy_item_new): New function.
> (btpy_list_item): Call btpy_item_new instead of recpy_insn_new.
> (recpy_bt_replay_position): Call btpy_item_new instead of
> btpy_insn_or_gap_new.
> (recpy_bt_begin): Call btpy_item_new instead of btpy_insn_or_gap_new.
> (recpy_bt_end): Call btpy_item_new instead of btpy_insn_or_gap_new.
> * py-record.c (recpy_aux_type): New static object.
> (recpy_aux_object): New typedef.
> (recpy_aux_new, recpy_aux_number, recpy_aux_data): New function.
> (recpy_aux_getset): New static object.
> (gdbpy_initialize_record): Initialize gdb.RecordAuxiliary type.
>
> gdb/doc/ChangeLog:
> * python.texi (gdb.RecordAuxiliary): New documentation.
>
> ---
> gdb/doc/python.texi | 13 +++++++
> gdb/python/py-record-btrace.c | 22 +++++++----
> gdb/python/py-record.c | 73 ++++++++++++++++++++++++++++++++++-
> gdb/python/py-record.h | 3 ++
> 4 files changed, 103 insertions(+), 8 deletions(-)
Looks good to me but I can't approve it.
> @@ -172,6 +173,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);
This must be true because we checked btrace_insn_get_error () before. To make it
more obvious, we could rewrite the function to call btrace_insn_get () first and check
the returned btrace_insn pointer. There's no need to check the error code, I think.
In the worst case, we'll end up with a gap that says 'success'.
> @@ -470,7 +479,7 @@ 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);
> + return btpy_item_new (obj->thread, number);
> else
> return recpy_func_new (obj->thread, RECORD_METHOD_BTRACE, number);
> }
Isn't this code just creating list item objects?
Thanks,
Markus.
Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Gary Kershaw
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
@@ -3495,6 +3495,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
@@ -150,10 +150,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;
@@ -172,6 +173,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[insn->aux_data_index].c_str (),
+ number);
+
return recpy_insn_new (tinfo, RECORD_METHOD_BTRACE, number);
}
@@ -470,7 +479,7 @@ 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);
+ return btpy_item_new (obj->thread, number);
else
return recpy_func_new (obj->thread, RECORD_METHOD_BTRACE, number);
}
@@ -658,8 +667,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
@@ -681,7 +689,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
@@ -703,7 +711,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
@@ -49,6 +49,12 @@ PyTypeObject recpy_gap_type = {
PyVarObject_HEAD_INIT (NULL, 0)
};
+/* Python RecordAuxiliary type. */
+
+PyTypeObject recpy_aux_type = {
+ PyVarObject_HEAD_INIT (NULL, 0)
+};
+
/* Python RecordGap object. */
typedef struct
{
@@ -64,6 +70,18 @@ typedef struct
Py_ssize_t number;
} recpy_gap_object;
+/* 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 PyString_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 == NULL)
+ return NULL;
+
+ 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 PyInt_FromSsize_t (obj->number);
+}
+
+/* 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 PyString_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, NULL, "element number", NULL},
+ { "data", recpy_aux_data, NULL, "data", NULL},
+ { NULL }
+};
+
/* 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;
@@ -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 */