Python: Move and rename gdb.BtraceFunction
authorTim Wiederhake <tim.wiederhake@intel.com>
Tue, 2 May 2017 09:35:54 +0000 (11:35 +0200)
committerTim Wiederhake <tim.wiederhake@intel.com>
Tue, 2 May 2017 09:35:54 +0000 (11:35 +0200)
Remove gdb.BtraceFunctionCall and replace by gdb.FunctionSegment.  Additionally,
rename prev_segment and next_segment to prev and next.

gdb/ChangeLog
gdb/doc/ChangeLog
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
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-record-btrace.exp

index 3d312b108cf4a7641eb54d97bab57ad1557d8012..041d9ac3ad4165554dea3b63a3aaf994ac55bd25 100644 (file)
@@ -1,3 +1,31 @@
+2017-05-01  Tim Wiederhake  <tim.wiederhake@intel.com>
+
+       * python/py-record-btrace.c (BTPY_REQUIRE_VALID_CALL, btpy_call_type):
+       Remove.
+       (btrace_func_from_recpy_func): New function.
+       (btpy_call_new, btpy_number, btpy_hash, btpy_richcompare): Remove.
+       (btpy_call_level, btpy_call_symbol, btpy_call_instructions,
+       btpy_call_up, btpy_call_prev_sibling, btpy_call_next_sibling): Rename to ...
+       (recpy_bt_func_level, recpy_bt_func_symbol, recpy_bt_func_instructions,
+       recpy_bt_func_up, recpy_bt_func_prev, recpy_bt_func_next): This.
+       Also, use new helper functions.
+       (btpy_list_item): Use new helper functions.
+       (recpy_bt_function_call_history): Use new type name.
+       (btpy_call_getset): Remove.
+       (gdbpy_initialize_btrace): Remove code to initialize
+       gdb.BtraceFunctionCall.
+       * python/py-record-btrace.h (recpy_bt_func_number, recpy_btb_func_level,
+       recpy_btb_func_symbol, recpy_bt_func_instructions, recpy_bt_func_up,
+       recpy_bt_func_prev, recpy_bt_func_next): New export.
+       * python/py-record.c (recpy_func_type): New static object.
+       (recpy_func_new, recpy_func_level, recpy_func_symbol,
+       recpy_func_instructions, recpy_func_up, recpy_func_prev,
+       recpy_func_next): New function.
+       (recpy_element_hash, recpy_element_richcompare): Updated comment.
+       (recpy_func_getset): New static object.
+       (gdbpy_initialize_record): Add code to initialize gdb.RecordInstruction.
+       * python/py-record.h (recpy_func_type, recpy_func_new): New export.
+
 2017-05-01  Tim Wiederhake  <tim.wiederhake@intel.com>
 
        * python/py-record-btrace.c (BTPY_REQUIRE_VALID_INSN): Remove.
index 1c43951a4ab2a261bb6dd280dc874bbf1529715b..f916167d4389a5ef1f7b22d1a95a99c2183aa65e 100644 (file)
@@ -1,3 +1,9 @@
+2017-05-01  Tim Wiederhake  <tim.wiederhake@intel.com>
+
+       * python.texi (Recording in Python): Replace gdb.BtraceFunction with
+       gdb.RecordFunctionSegment.  Rename prev_sibling and next_sibling to
+       prev and next.
+
 2017-05-01  Tim Wiederhake  <tim.wiederhake@intel.com>
 
        * python.texi (Recording in Python): Replace gdb.BtraceInstruction with
index 84fe7d5a63effa22021d7100308c28cb53ad764e..da579fc6f302d3a8f9b050425943704ade863cde 100644 (file)
@@ -3203,48 +3203,43 @@ the current recording method.
 A human readable string with the reason for the gap.
 @end defvar
 
-The attributes and methods of function call objects depend on the
-current recording format.  Currently, only btrace function calls are
-supported.
+A @code{gdb.RecordFunctionSegment} object has the following attributes:
 
-A @code{gdb.BtraceFunctionCall} object has the following attributes:
-
-@defvar BtraceFunctionCall.number
-An integer identifying this function call.  @var{number} corresponds to
+@defvar RecordFunctionSegment.number
+An integer identifying this function segment.  @code{number} corresponds to
 the numbers seen in @code{record function-call-history}
 (@pxref{Process Record and Replay}).
 @end defvar
 
-@defvar BtraceFunctionCall.symbol
+@defvar RecordFunctionSegment.symbol
 A @code{gdb.Symbol} object representing the associated symbol.  May be
-@code{None} if the function call is a gap or the debug symbols could
-not be read.
+@code{None} if no debug information is available.
 @end defvar
 
-@defvar BtraceFunctionCall.level
+@defvar RecordFunctionSegment.level
 An integer representing the function call's stack level.  May be
 @code{None} if the function call is a gap.
 @end defvar
 
-@defvar BtraceFunctionCall.instructions
+@defvar RecordFunctionSegment.instructions
 A list of @code{gdb.RecordInstruction} or @code{gdb.RecordGap} objects
 associated with this function call.
 @end defvar
 
-@defvar BtraceFunctionCall.up
-A @code{gdb.BtraceFunctionCall} object representing the caller's
+@defvar RecordFunctionSegment.up
+A @code{gdb.RecordFunctionSegment} object representing the caller's
 function segment.  If the call has not been recorded, this will be the
 function segment to which control returns.  If neither the call nor the
 return have been recorded, this will be @code{None}.
 @end defvar
 
-@defvar BtraceFunctionCall.prev_sibling
-A @code{gdb.BtraceFunctionCall} object representing the previous
+@defvar RecordFunctionSegment.prev
+A @code{gdb.RecordFunctionSegment} object representing the previous
 segment of this function call.  May be @code{None}.
 @end defvar
 
-@defvar BtraceFunctionCall.next_sibling
-A @code{gdb.BtraceFunctionCall} object representing the next segment of
+@defvar RecordFunctionSegment.next
+A @code{gdb.RecordFunctionSegment} object representing the next segment of
 this function call.  May be @code{None}.
 @end defvar
 
index 85fb531eba7c589b643b3adc5fc14970737836ca..d68456161d0669bc042781451f018178847349b0 100644 (file)
 
 #endif
 
-#define BTPY_REQUIRE_VALID_CALL(obj, iter)                             \
-  do {                                                                 \
-    struct thread_info *tinfo = find_thread_ptid (obj->ptid);          \
-    if (tinfo == NULL || btrace_is_empty (tinfo))                      \
-      return PyErr_Format (gdbpy_gdb_error, _("Empty branch trace.")); \
-    if (0 == btrace_find_call_by_number (&iter, &tinfo->btrace,                \
-                                        obj->number))                  \
-      return PyErr_Format (gdbpy_gdb_error, _("No such call segment."));\
-  } while (0)
-
 /* Python object for btrace record lists.  */
 
 typedef struct {
@@ -67,12 +57,6 @@ typedef struct {
   PyTypeObject* element_type;
 } btpy_list_object;
 
-/* Python type for btrace function-calls.  */
-
-static PyTypeObject btpy_call_type = {
-  PyVarObject_HEAD_INIT (NULL, 0)
-};
-
 /* Python type for btrace lists.  */
 
 static PyTypeObject btpy_list_type = {
@@ -121,6 +105,49 @@ btrace_insn_from_recpy_insn (const PyObject * const pyobject)
   return insn;
 }
 
+/* Returns either a btrace_function for the given Python
+   gdb.RecordFunctionSegment object or sets an appropriate Python exception and
+   returns NULL.  */
+
+static const btrace_function *
+btrace_func_from_recpy_func (const PyObject * const pyobject)
+{
+  const btrace_function *func;
+  const recpy_element_object *obj;
+  thread_info *tinfo;
+  btrace_call_iterator iter;
+
+  if (Py_TYPE (pyobject) != &recpy_func_type)
+    {
+      PyErr_Format (gdbpy_gdb_error, _("Must be gdb.RecordFunctionSegment"));
+      return NULL;
+    }
+
+  obj = (const recpy_element_object *) pyobject;
+  tinfo = find_thread_ptid (obj->ptid);
+
+  if (tinfo == NULL || btrace_is_empty (tinfo))
+    {
+      PyErr_Format (gdbpy_gdb_error, _("No such function segment."));
+      return NULL;
+    }
+
+  if (btrace_find_call_by_number (&iter, &tinfo->btrace, obj->number) == 0)
+    {
+      PyErr_Format (gdbpy_gdb_error, _("No such function segment."));
+      return NULL;
+    }
+
+  func = btrace_call_get (&iter);
+  if (func == NULL)
+    {
+      PyErr_Format (gdbpy_gdb_error, _("Not a valid function segment."));
+      return NULL;
+    }
+
+  return func;
+}
+
 /* Looks at the recorded item with the number NUMBER and create a
    gdb.RecordInstruction or gdb.RecordGap object for it accordingly.  */
 
@@ -147,24 +174,6 @@ btpy_insn_or_gap_new (const thread_info *tinfo, Py_ssize_t number)
   return recpy_insn_new (tinfo->ptid, RECORD_METHOD_BTRACE, number);
 }
 
-/* Create a new gdb.BtraceFunctionCall object.  */
-
-static PyObject *
-btpy_call_new (ptid_t ptid, Py_ssize_t number)
-{
-  recpy_element_object * const obj = PyObject_New (recpy_element_object,
-                                                  &btpy_call_type);
-
-  if (obj == NULL)
-    return NULL;
-
-  obj->ptid = ptid;
-  obj->method = RECORD_METHOD_BTRACE;
-  obj->number = number;
-
-  return (PyObject *) obj;
-}
-
 /* Create a new gdb.BtraceList object.  */
 
 static PyObject *
@@ -186,28 +195,6 @@ btpy_list_new (ptid_t ptid, Py_ssize_t first, Py_ssize_t last, Py_ssize_t step,
   return (PyObject *) obj;
 }
 
-/* Implementation of BtraceInstruction.number [int] and
-   BtraceFunctionCall.number [int].  */
-
-static PyObject *
-btpy_number (PyObject *self, void *closure)
-{
-  const recpy_element_object * const obj = (const recpy_element_object *) self;
-
-  return PyInt_FromSsize_t (obj->number);
-}
-
-/* Implementation of BtraceInstruction.__hash__ () -> int and
-   BtraceFunctionCall.__hash__ () -> int.  */
-
-static Py_hash_t
-btpy_hash (PyObject *self)
-{
-  const recpy_element_object * const obj = (const recpy_element_object *) self;
-
-  return obj->number;
-}
-
 /* Implementation of RecordInstruction.sal [gdb.Symtab_and_line] for btrace.
    Returns the SAL associated with this instruction.  */
 
@@ -344,40 +331,32 @@ recpy_bt_insn_decoded (PyObject *self, void *closure)
   return PyBytes_FromString (strfile.string ().c_str ());
 }
 
-/* Implementation of BtraceFunctionCall.level [int].  Returns the
-   call level.  */
+/* Implementation of RecordFunctionSegment.level [int] for btrace.
+   Returns the call level.  */
 
-static PyObject *
-btpy_call_level (PyObject *self, void *closure)
+PyObject *
+recpy_bt_func_level (PyObject *self, void *closure)
 {
-  const recpy_element_object * const obj = (const recpy_element_object *) self;
-  const struct btrace_function *func;
-  struct btrace_call_iterator iter;
-
-  BTPY_REQUIRE_VALID_CALL (obj, iter);
+  const btrace_function * const func = btrace_func_from_recpy_func (self);
+  thread_info *tinfo;
 
-  func = btrace_call_get (&iter);
   if (func == NULL)
-    Py_RETURN_NONE;
+    return NULL;
 
-  return PyInt_FromLong (iter.btinfo->level + func->level);
+  tinfo = find_thread_ptid (((recpy_element_object *) self)->ptid);
+  return PyInt_FromLong (tinfo->btrace.level + func->level);
 }
 
-/* Implementation of BtraceFunctionCall.symbol [gdb.Symbol].  Returns
-   the symbol associated with this function call.  */
+/* Implementation of RecordFunctionSegment.symbol [gdb.Symbol] for btrace.
+   Returns the symbol associated with this function call.  */
 
-static PyObject *
-btpy_call_symbol (PyObject *self, void *closure)
+PyObject *
+recpy_bt_func_symbol (PyObject *self, void *closure)
 {
-  const recpy_element_object * const obj = (const recpy_element_object *) self;
-  const struct btrace_function *func;
-  struct btrace_call_iterator iter;
+  const btrace_function * const func = btrace_func_from_recpy_func (self);
 
-  BTPY_REQUIRE_VALID_CALL (obj, iter);
-
-  func = btrace_call_get (&iter);
   if (func == NULL)
-    Py_RETURN_NONE;
+    return NULL;
 
   if (func->sym == NULL)
     Py_RETURN_NONE;
@@ -385,22 +364,17 @@ btpy_call_symbol (PyObject *self, void *closure)
   return symbol_to_symbol_object (func->sym);
 }
 
-/* Implementation of BtraceFunctionCall.instructions [list].
-   Return the list of instructions that belong to this function call.  */
+/* Implementation of RecordFunctionSegment.instructions [list] for btrace.
+   Returns the list of instructions that belong to this function call.  */
 
-static PyObject *
-btpy_call_instructions (PyObject *self, void *closure)
+PyObject *
+recpy_bt_func_instructions (PyObject *self, void *closure)
 {
-  const recpy_element_object * const obj = (const recpy_element_object *) self;
-  const struct btrace_function *func;
-  struct btrace_call_iterator iter;
+  const btrace_function * const func = btrace_func_from_recpy_func (self);
   unsigned int len;
 
-  BTPY_REQUIRE_VALID_CALL (obj, iter);
-
-  func = btrace_call_get (&iter);
   if (func == NULL)
-    Py_RETURN_NONE;
+    return NULL;
 
   len = VEC_length (btrace_insn_s, func->insn);
 
@@ -408,111 +382,63 @@ btpy_call_instructions (PyObject *self, void *closure)
   if (len == 0)
     len = 1;
 
-  return btpy_list_new (obj->ptid, func->insn_offset, func->insn_offset + len,
-                       1, &recpy_insn_type);
+  return btpy_list_new (((recpy_element_object *) self)->ptid,
+                       func->insn_offset, func->insn_offset + len, 1,
+                       &recpy_insn_type);
 }
 
-/* Implementation of BtraceFunctionCall.up [gdb.BtraceRecordCall].
-   Return the caller / returnee of this function.  */
+/* Implementation of RecordFunctionSegment.up [RecordFunctionSegment] for
+   btrace.  Returns the caller / returnee of this function.  */
 
-static PyObject *
-btpy_call_up (PyObject *self, void *closure)
+PyObject *
+recpy_bt_func_up (PyObject *self, void *closure)
 {
-  const recpy_element_object * const obj = (const recpy_element_object *) self;
-  const struct btrace_function *func;
-  struct btrace_call_iterator iter;
-
-  BTPY_REQUIRE_VALID_CALL (obj, iter);
+  const btrace_function * const func = btrace_func_from_recpy_func (self);
 
-  func = btrace_call_get (&iter);
   if (func == NULL)
-    Py_RETURN_NONE;
+    return NULL;
 
   if (func->up == NULL)
     Py_RETURN_NONE;
 
-  return btpy_call_new (obj->ptid, func->up->number);
+  return recpy_func_new (((recpy_element_object *) self)->ptid,
+                        RECORD_METHOD_BTRACE, func->up->number);
 }
 
-/* Implementation of BtraceFunctionCall.prev_sibling [BtraceFunctionCall].
-   Return a previous segment of this function.  */
+/* Implementation of RecordFunctionSegment.prev [RecordFunctionSegment] for
+   btrace.  Returns a previous segment of this function.  */
 
-static PyObject *
-btpy_call_prev_sibling (PyObject *self, void *closure)
+PyObject *
+recpy_bt_func_prev (PyObject *self, void *closure)
 {
-  const recpy_element_object * const obj = (const recpy_element_object *) self;
-  const struct btrace_function *func;
-  struct btrace_call_iterator iter;
-
-  BTPY_REQUIRE_VALID_CALL (obj, iter);
+  const btrace_function * const func = btrace_func_from_recpy_func (self);
 
-  func = btrace_call_get (&iter);
   if (func == NULL)
-    Py_RETURN_NONE;
+    return NULL;
 
   if (func->segment.prev == NULL)
     Py_RETURN_NONE;
 
-  return btpy_call_new (obj->ptid, func->segment.prev->number);
+  return recpy_func_new (((recpy_element_object *) self)->ptid,
+                        RECORD_METHOD_BTRACE, func->segment.prev->number);
 }
 
-/* Implementation of BtraceFunctionCall.next_sibling [BtraceFunctionCall].
-   Return a following segment of this function.  */
+/* Implementation of RecordFunctionSegment.next [RecordFunctionSegment] for
+   btrace.  Returns a following segment of this function.  */
 
-static PyObject *
-btpy_call_next_sibling (PyObject *self, void *closure)
+PyObject *
+recpy_bt_func_next (PyObject *self, void *closure)
 {
-  const recpy_element_object * const obj = (const recpy_element_object *) self;
-  const struct btrace_function *func;
-  struct btrace_call_iterator iter;
+  const btrace_function * const func = btrace_func_from_recpy_func (self);
 
-  BTPY_REQUIRE_VALID_CALL (obj, iter);
-
-  func = btrace_call_get (&iter);
   if (func == NULL)
-    Py_RETURN_NONE;
+    return NULL;
 
   if (func->segment.next == NULL)
     Py_RETURN_NONE;
 
-  return btpy_call_new (obj->ptid, func->segment.next->number);
-}
-
-/* Python rich compare function to allow for equality and inequality checks
-   in Python.  */
-
-static PyObject *
-btpy_richcompare (PyObject *self, PyObject *other, int op)
-{
-  const recpy_element_object * const obj1 = (recpy_element_object *) self;
-  const recpy_element_object * const obj2 = (recpy_element_object *) other;
-
-  if (Py_TYPE (self) != Py_TYPE (other))
-    {
-      Py_INCREF (Py_NotImplemented);
-      return Py_NotImplemented;
-    }
-
-  switch (op)
-  {
-    case Py_EQ:
-      if (ptid_equal (obj1->ptid, obj2->ptid) && obj1->number == obj2->number)
-       Py_RETURN_TRUE;
-      else
-       Py_RETURN_FALSE;
-
-    case Py_NE:
-      if (!ptid_equal (obj1->ptid, obj2->ptid) || obj1->number != obj2->number)
-       Py_RETURN_TRUE;
-      else
-       Py_RETURN_FALSE;
-
-    default:
-      break;
-  }
-
-  Py_INCREF (Py_NotImplemented);
-  return Py_NotImplemented;
+  return recpy_func_new (((recpy_element_object *) self)->ptid,
+                        RECORD_METHOD_BTRACE, func->segment.next->number);
 }
 
 /* Implementation of BtraceList.__len__ (self) -> int.  */
@@ -550,7 +476,7 @@ btpy_list_item (PyObject *self, Py_ssize_t index)
   if (obj->element_type == &recpy_insn_type)
     return recpy_insn_new (obj->ptid, RECORD_METHOD_BTRACE, number);
   else
-    return btpy_call_new (obj->ptid, number);
+    return recpy_func_new (obj->ptid, RECORD_METHOD_BTRACE, number);
 }
 
 /* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList.  */
@@ -839,7 +765,7 @@ recpy_bt_function_call_history (PyObject *self, void *closure)
   btrace_call_end (&iterator, &tinfo->btrace);
   last = btrace_call_number (&iterator);
 
-  return btpy_list_new (record->ptid, first, last, 1, &btpy_call_type);
+  return btpy_list_new (record->ptid, first, last, 1, &recpy_func_type);
 }
 
 /* Implementation of BtraceRecord.goto (self, BtraceInstruction) -> None.  */
@@ -880,23 +806,6 @@ recpy_bt_goto (PyObject *self, PyObject *args)
   Py_RETURN_NONE;
 }
 
-/* BtraceFunctionCall members.  */
-
-static gdb_PyGetSetDef btpy_call_getset[] =
-{
-  { "number", btpy_number, NULL, "function call number", NULL},
-  { "level", btpy_call_level, NULL, "call stack level", NULL},
-  { "symbol", btpy_call_symbol, NULL, "associated line and symbol", NULL},
-  { "instructions", btpy_call_instructions, NULL, "list of instructions in \
-this function segment", NULL},
-  { "up", btpy_call_up, NULL, "caller or returned-to function segment", NULL},
-  { "prev_sibling", btpy_call_prev_sibling, NULL, "previous segment of this \
-function", NULL},
-  { "next_sibling", btpy_call_next_sibling, NULL, "next segment of this \
-function", NULL},
-  {NULL}
-};
-
 /* BtraceList methods.  */
 
 struct PyMethodDef btpy_list_methods[] =
@@ -925,15 +834,6 @@ static PyMappingMethods btpy_list_mapping_methods =
 int
 gdbpy_initialize_btrace (void)
 {
-  btpy_call_type.tp_new = PyType_GenericNew;
-  btpy_call_type.tp_flags = Py_TPFLAGS_DEFAULT;
-  btpy_call_type.tp_basicsize = sizeof (recpy_element_object);
-  btpy_call_type.tp_name = "gdb.BtraceFunctionCall";
-  btpy_call_type.tp_doc = "GDB btrace call object";
-  btpy_call_type.tp_getset = btpy_call_getset;
-  btpy_call_type.tp_richcompare = btpy_richcompare;
-  btpy_call_type.tp_hash = btpy_hash;
-
   btpy_list_type.tp_new = PyType_GenericNew;
   btpy_list_type.tp_flags = Py_TPFLAGS_DEFAULT;
   btpy_list_type.tp_basicsize = sizeof (btpy_list_object);
@@ -950,9 +850,5 @@ gdbpy_initialize_btrace (void)
 
   btpy_list_mapping_methods.mp_subscript = btpy_list_slice;
 
-  if (PyType_Ready (&btpy_call_type) < 0
-      || PyType_Ready (&btpy_list_type) < 0)
-    return -1;
-  else
-    return 0;
+  return PyType_Ready (&btpy_list_type);
 }
index 945129dbeabd27263166b1281ce70b0a3e5f3401..81b60ae43d785077557685a88155d0b1b66290d8 100644 (file)
@@ -67,4 +67,25 @@ extern PyObject *recpy_bt_insn_size (PyObject *self, void *closure);
 /* Implementation of RecordInstruction.is_speculative [bool].  */
 extern PyObject *recpy_bt_insn_is_speculative (PyObject *self, void *closure);
 
+/* Implementation of RecordFunctionSegment.number [int].  */
+extern PyObject *recpy_bt_func_number (PyObject *self, void *closure);
+
+/* Implementation of RecordFunctionSegment.number [int].  */
+extern PyObject *recpy_bt_func_level (PyObject *self, void *closure);
+
+/* Implementation of RecordFunctionSegment.symbol [gdb.Symbol].  */
+extern PyObject *recpy_bt_func_symbol (PyObject *self, void *closure);
+
+/* Implementation of RecordFunctionSegment.instructions [list].  */
+extern PyObject *recpy_bt_func_instructions (PyObject *self, void *closure);
+
+/* Implementation of RecordFunctionSegment.up [RecordFunctionSegment].  */
+extern PyObject *recpy_bt_func_up (PyObject *self, void *closure);
+
+/* Implementation of RecordFunctionSegment.prev [RecordFunctionSegment].  */
+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);
+
 #endif /* GDB_PY_RECORD_BTRACE_H */
index bdc2a3b30f7bc5c6cd5bac565a7e8e8fd9ff3f23..d308a947691c82623d8a89710dca4baadf5f9df8 100644 (file)
@@ -35,6 +35,12 @@ PyTypeObject recpy_insn_type = {
   PyVarObject_HEAD_INIT (NULL, 0)
 };
 
+/* Python RecordFunctionSegment type.  */
+
+PyTypeObject recpy_func_type = {
+  PyVarObject_HEAD_INIT (NULL, 0)
+};
+
 /* Python RecordGap type.  */
 
 PyTypeObject recpy_gap_type = {
@@ -262,7 +268,104 @@ recpy_insn_is_speculative (PyObject *self, void *closure)
   return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
 }
 
-/* Implementation of RecordInstruction.number [int].  */
+/* Create a new gdb.RecordFunctionSegment object.  */
+
+PyObject *
+recpy_func_new (ptid_t ptid, enum record_method method, Py_ssize_t number)
+{
+  recpy_element_object * const obj = PyObject_New (recpy_element_object,
+                                                  &recpy_func_type);
+
+  if (obj == NULL)
+   return NULL;
+
+  obj->ptid = ptid;
+  obj->method = method;
+  obj->number = number;
+
+  return (PyObject *) obj;
+}
+
+/* Implementation of RecordFunctionSegment.level [int].  */
+
+static PyObject *
+recpy_func_level (PyObject *self, void *closure)
+{
+  const recpy_element_object * const obj = (recpy_element_object *) self;
+
+  if (obj->method == RECORD_METHOD_BTRACE)
+    return recpy_bt_func_level (self, closure);
+
+  return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordFunctionSegment.symbol [gdb.Symbol].  */
+
+static PyObject *
+recpy_func_symbol (PyObject *self, void *closure)
+{
+  const recpy_element_object * const obj = (recpy_element_object *) self;
+
+  if (obj->method == RECORD_METHOD_BTRACE)
+    return recpy_bt_func_symbol (self, closure);
+
+  return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordFunctionSegment.instructions [list].  */
+
+static PyObject *
+recpy_func_instructions (PyObject *self, void *closure)
+{
+  const recpy_element_object * const obj = (recpy_element_object *) self;
+
+  if (obj->method == RECORD_METHOD_BTRACE)
+    return recpy_bt_func_instructions (self, closure);
+
+  return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordFunctionSegment.up [RecordFunctionSegment].  */
+
+static PyObject *
+recpy_func_up (PyObject *self, void *closure)
+{
+  const recpy_element_object * const obj = (recpy_element_object *) self;
+
+  if (obj->method == RECORD_METHOD_BTRACE)
+    return recpy_bt_func_up (self, closure);
+
+  return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordFunctionSegment.prev [RecordFunctionSegment].  */
+
+static PyObject *
+recpy_func_prev (PyObject *self, void *closure)
+{
+  const recpy_element_object * const obj = (recpy_element_object *) self;
+
+  if (obj->method == RECORD_METHOD_BTRACE)
+    return recpy_bt_func_prev (self, closure);
+
+  return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordFunctionSegment.next [RecordFunctionSegment].  */
+
+static PyObject *
+recpy_func_next (PyObject *self, void *closure)
+{
+  const recpy_element_object * const obj = (recpy_element_object *) self;
+
+  if (obj->method == RECORD_METHOD_BTRACE)
+    return recpy_bt_func_next (self, closure);
+
+  return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordInstruction.number [int] and
+   RecordFunctionSegment.number [int].  */
 
 static PyObject *
 recpy_element_number (PyObject *self, void* closure)
@@ -272,7 +375,9 @@ recpy_element_number (PyObject *self, void* closure)
   return PyInt_FromSsize_t (obj->number);
 }
 
-/* Implementation of RecordInstruction.__hash__ [int].  */
+/* Implementation of RecordInstruction.__hash__ [int] and
+   RecordFunctionSegment.__hash__ [int].  */
+
 static Py_hash_t
 recpy_element_hash (PyObject *self)
 {
@@ -281,7 +386,8 @@ recpy_element_hash (PyObject *self)
   return obj->number;
 }
 
-/* Implementation of operator == and != of RecordInstruction.  */
+/* Implementation of operator == and != of RecordInstruction and
+   RecordFunctionSegment.  */
 
 static PyObject *
 recpy_element_richcompare (PyObject *self, PyObject *other, int op)
@@ -411,6 +517,20 @@ static gdb_PyGetSetDef recpy_insn_getset[] = {
   { NULL }
 };
 
+/* RecordFunctionSegment member list.  */
+
+static gdb_PyGetSetDef recpy_func_getset[] = {
+  { "number", recpy_element_number, NULL, "function segment number", NULL},
+  { "level", recpy_func_level, NULL, "call stack level", NULL},
+  { "symbol", recpy_func_symbol, NULL, "associated line and symbol", NULL},
+  { "instructions", recpy_func_instructions, NULL, "list of instructions in \
+this function segment", NULL},
+  { "up", recpy_func_up, NULL, "caller or returned-to function segment", NULL},
+  { "prev", recpy_func_prev, NULL, "previous segment of this function", NULL},
+  { "next", recpy_func_next, NULL, "next segment of this function", NULL},
+  { NULL }
+};
+
 /* RecordGap member list.  */
 
 static gdb_PyGetSetDef recpy_gap_getset[] = {
@@ -442,6 +562,15 @@ gdbpy_initialize_record (void)
   recpy_insn_type.tp_richcompare = recpy_element_richcompare;
   recpy_insn_type.tp_hash = recpy_element_hash;
 
+  recpy_func_type.tp_new = PyType_GenericNew;
+  recpy_func_type.tp_flags = Py_TPFLAGS_DEFAULT;
+  recpy_func_type.tp_basicsize = sizeof (recpy_element_object);
+  recpy_func_type.tp_name = "gdb.RecordFunctionSegment";
+  recpy_func_type.tp_doc = "GDB record function segment object";
+  recpy_func_type.tp_getset = recpy_func_getset;
+  recpy_func_type.tp_richcompare = recpy_element_richcompare;
+  recpy_func_type.tp_hash = recpy_element_hash;
+
   recpy_gap_type.tp_new = PyType_GenericNew;
   recpy_gap_type.tp_flags = Py_TPFLAGS_DEFAULT;
   recpy_gap_type.tp_basicsize = sizeof (recpy_gap_object);
@@ -451,6 +580,7 @@ gdbpy_initialize_record (void)
 
   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)
     return -1;
   else
index ae2d2d2c860f28606738cd6f9666c86e74928796..062abb2aa707d70af3586f88c9006f28724accff 100644 (file)
@@ -56,10 +56,17 @@ typedef struct
 /* Python RecordInstruction type.  */
 extern PyTypeObject recpy_insn_type;
 
+/* Python RecordFunctionSegment type.  */
+extern PyTypeObject recpy_func_type;
+
 /* Create a new gdb.RecordInstruction object.  */
 extern PyObject *recpy_insn_new (ptid_t ptid, enum record_method method,
                                 Py_ssize_t number);
 
+/* Create a new gdb.RecordFunctionSegment object.  */
+extern PyObject *recpy_func_new (ptid_t ptid, enum record_method method,
+                                Py_ssize_t number);
+
 /* Create a new gdb.RecordGap object.  */
 extern PyObject *recpy_gap_new (int reason_code, const char *reason_string,
                                Py_ssize_t number);
index f30fa48e6c007895d9489239ea8041af6c7d1313..9c0d68b529badb8e17a27a00546fa2262e64cc98 100644 (file)
@@ -1,3 +1,8 @@
+2017-05-01  Tim Wiederhake  <tim.wiederhake@intel.com>
+
+       * gdb.python/py-record-btrace.exp: Rename prev_sibling and next_sibling
+       to prev and next.
+
 2017-05-01  Tim Wiederhake  <tim.wiederhake@intel.com>
 
        * gdb.python/py-record-btrace.exp: Remove test for
index 045e63eb389983fd07f094e3c173a3d163594a6a..cda822dfa6c5cdee1001aad474deaaa8a295cae1 100644 (file)
@@ -99,8 +99,8 @@ with_test_prefix "function call" {
     gdb_test "python print(c.level)" "$decimal"
     gdb_test "python print(len(c.instructions))" "$decimal"
     gdb_test "python print(c.up)" "None"
-    gdb_test "python print(c.prev_sibling)" "None"
-    gdb_test "python print(c == c.next_sibling.prev_sibling)" "True"
+    gdb_test "python print(c.prev)" "None"
+    gdb_test "python print(c == c.next.prev)" "True"
 }
 
 with_test_prefix "list" {