]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
python: Introduce gdb.RecordAuxiliary class.
authorFelix Willgerodt <felix.willgerodt@intel.com>
Thu, 21 Feb 2019 09:48:35 +0000 (10:48 +0100)
committerFelix Willgerodt <felix.willgerodt@intel.com>
Wed, 14 Aug 2024 09:20:56 +0000 (11:20 +0200)
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>
gdb/doc/python.texi
gdb/python/py-record-btrace.c
gdb/python/py-record-btrace.h
gdb/python/py-record.c
gdb/python/py-record.h

index 86ccc140c6de2ea8d40208bd8867ce080ce49fef..05e50591d9946d059a88aefb2361a4065e1abbc4 100644 (file)
@@ -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
index 36454fc669fc1fa2cd0fb7116207cb048ca2dfdb..0ff2708801be19abd3f355b6a16741fbaf93a0f4 100644 (file)
@@ -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
index 8678e77322b2e0265b3d16d2f31b822f9013cf50..5010cb3f95dd7ad5400ff8683831dab8d5c96e51 100644 (file)
@@ -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 */
index d4891268e03664e5c6db9c6056fbf4a8ccc79572..0efd631200b79e5b90f28f651931dcf4c2e6a09d 100644 (file)
@@ -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;
index 7e1161005b484ab80ca9b3e678ca6212cc3a4c3a..0988584abeabc41c1b5bd686b37e5e3157b512c8 100644 (file)
@@ -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 */