This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v3 6/8] Python: Move and rename gdb.BtraceFunction


Remove gdb.BtraceFunctionCall and replace by gdb.FunctionSegment.  Additionally,
rename prev_segment and next_segment to prev and next.

2017-04-24  Tim Wiederhake  <tim.wiederhake@intel.com>

gdb/ChangeLog:
	* 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.

gdb/doc/ChangeLog:
	* python.texi (Recording in Python): Replace gdb.BtraceFunction with
	gdb.RecordFunctionSegment.  Rename prev_sibling and next_sibling to
	prev and next.

gdb/testsuite/ChangeLog:
	* gdb.python/py-record-btrace.exp: Rename prev_sibling and next_sibling
	to prev and next.

---
 gdb/doc/python.texi                           |  31 ++-
 gdb/python/py-record-btrace.c                 | 292 +++++++++-----------------
 gdb/python/py-record-btrace.h                 |  21 ++
 gdb/python/py-record.c                        | 136 +++++++++++-
 gdb/python/py-record.h                        |   7 +
 gdb/testsuite/gdb.python/py-record-btrace.exp |   4 +-
 6 files changed, 270 insertions(+), 221 deletions(-)

diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 84fe7d5..da579fc 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -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
 
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 85fb531..d684561 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -36,16 +36,6 @@
 
 #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);
 }
diff --git a/gdb/python/py-record-btrace.h b/gdb/python/py-record-btrace.h
index 945129d..81b60ae 100644
--- a/gdb/python/py-record-btrace.h
+++ b/gdb/python/py-record-btrace.h
@@ -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 */
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index bdc2a3b..d308a94 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -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
diff --git a/gdb/python/py-record.h b/gdb/python/py-record.h
index ae2d2d2..062abb2 100644
--- a/gdb/python/py-record.h
+++ b/gdb/python/py-record.h
@@ -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);
diff --git a/gdb/testsuite/gdb.python/py-record-btrace.exp b/gdb/testsuite/gdb.python/py-record-btrace.exp
index 045e63e..cda822d 100644
--- a/gdb/testsuite/gdb.python/py-record-btrace.exp
+++ b/gdb/testsuite/gdb.python/py-record-btrace.exp
@@ -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" {
-- 
2.7.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]